cmd: DIR command outputs free space for the path.
[wine.git] / dlls / crypt32 / decode.c
blob6d683974f44adf2d01bf309ee3be27df589df94d
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 #include "windef.h"
39 #include "winbase.h"
40 #include "wincrypt.h"
41 #include "winnls.h"
42 #include "snmp.h"
43 #include "wine/debug.h"
44 #include "wine/exception.h"
45 #include "crypt32_private.h"
47 /* This is a bit arbitrary, but to set some limit: */
48 #define MAX_ENCODED_LEN 0x04000000
50 #define ASN_FLAGS_MASK 0xe0
51 #define ASN_TYPE_MASK 0x1f
53 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
54 WINE_DECLARE_DEBUG_CHANNEL(crypt);
56 void CRYPT_CopyReversed(BYTE *dst, const BYTE *src, size_t len)
58 DWORD i;
59 for (i = 0; i < len; i++) {
60 dst[len - i - 1] = src[i];
64 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
65 DWORD, DWORD, void *, DWORD *);
66 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
67 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
69 /* Internal decoders don't do memory allocation or exception handling, and
70 * they report how many bytes they decoded.
72 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
73 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
75 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
76 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
77 DWORD *pcbDecoded);
78 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
79 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
80 DWORD *pcbDecoded);
81 /* Assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set ahead of time.
83 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
84 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
85 /* Assumes algo->Parameters.pbData is set ahead of time. */
86 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
87 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
88 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
89 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
90 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
91 static BOOL CRYPT_AsnDecodeOctets(const BYTE *pbEncoded,
92 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
93 DWORD *pcbDecoded);
94 /* Doesn't check the tag, assumes the caller does so */
95 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
96 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
97 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
98 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
99 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
100 * member has been initialized, doesn't do exception handling, and doesn't do
101 * memory allocation. Also doesn't check tag, assumes the caller has checked
102 * it.
104 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
105 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
106 DWORD *pcbDecoded);
107 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
108 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
109 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
110 DWORD *pcbDecoded);
111 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
112 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
113 DWORD *pcbDecoded);
115 /* Gets the number of length bytes from the given (leading) length byte */
116 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
118 /* Helper function to get the encoded length of the data starting at pbEncoded,
119 * where pbEncoded[0] is the tag. If the data are too short to contain a
120 * length or if the length is too large for cbEncoded, sets an appropriate
121 * error code and returns FALSE. If the encoded length is unknown due to
122 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
124 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
125 DWORD *len)
127 BOOL ret;
129 if (cbEncoded <= 1)
131 SetLastError(CRYPT_E_ASN1_CORRUPT);
132 ret = FALSE;
134 else if (pbEncoded[1] <= 0x7f)
136 if (pbEncoded[1] + 1 > cbEncoded)
138 SetLastError(CRYPT_E_ASN1_EOD);
139 ret = FALSE;
141 else
143 *len = pbEncoded[1];
144 ret = TRUE;
147 else if (pbEncoded[1] == 0x80)
149 *len = CMSG_INDEFINITE_LENGTH;
150 ret = TRUE;
152 else
154 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
156 if (lenLen > sizeof(DWORD) + 1)
158 SetLastError(CRYPT_E_ASN1_LARGE);
159 ret = FALSE;
161 else if (lenLen + 2 > cbEncoded)
163 SetLastError(CRYPT_E_ASN1_CORRUPT);
164 ret = FALSE;
166 else
168 DWORD out = 0;
170 pbEncoded += 2;
171 while (--lenLen)
173 out <<= 8;
174 out |= *pbEncoded++;
176 if (out + lenLen + 1 > cbEncoded)
178 SetLastError(CRYPT_E_ASN1_EOD);
179 ret = FALSE;
181 else
183 *len = out;
184 ret = TRUE;
188 return ret;
191 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
192 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
194 BOOL ret;
196 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
197 *len == CMSG_INDEFINITE_LENGTH)
199 SetLastError(CRYPT_E_ASN1_CORRUPT);
200 ret = FALSE;
202 return ret;
205 /* Helper function to check *pcbStructInfo, set it to the required size, and
206 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
207 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
208 * pointer to the newly allocated memory.
210 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
211 const CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
212 DWORD bytesNeeded)
214 BOOL ret = TRUE;
216 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
218 if (pDecodePara && pDecodePara->pfnAlloc)
219 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
220 else
221 *(BYTE **)pvStructInfo = LocalAlloc(LPTR, bytesNeeded);
222 if (!*(BYTE **)pvStructInfo)
223 ret = FALSE;
224 else
225 *pcbStructInfo = bytesNeeded;
227 else if (*pcbStructInfo < bytesNeeded)
229 *pcbStructInfo = bytesNeeded;
230 SetLastError(ERROR_MORE_DATA);
231 ret = FALSE;
233 else
234 *pcbStructInfo = bytesNeeded;
235 return ret;
238 static void CRYPT_FreeSpace(const CRYPT_DECODE_PARA *pDecodePara, LPVOID pv)
240 if (pDecodePara && pDecodePara->pfnFree)
241 pDecodePara->pfnFree(pv);
242 else
243 LocalFree(pv);
246 /* Helper function to check *pcbStructInfo and set it to the required size.
247 * Assumes pvStructInfo is not NULL.
249 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
251 BOOL ret;
253 if (*pcbStructInfo < bytesNeeded)
255 *pcbStructInfo = bytesNeeded;
256 SetLastError(ERROR_MORE_DATA);
257 ret = FALSE;
259 else
261 *pcbStructInfo = bytesNeeded;
262 ret = TRUE;
264 return ret;
267 /* tag:
268 * The expected tag of the item. If tag is 0, decodeFunc is called
269 * regardless of the tag value seen.
270 * offset:
271 * A sequence is decoded into a struct. The offset member is the
272 * offset of this item within that struct.
273 * decodeFunc:
274 * The decoder function to use. If this is NULL, then the member isn't
275 * decoded, but minSize space is reserved for it.
276 * minSize:
277 * The minimum amount of space occupied after decoding. You must set this.
278 * optional:
279 * If true, and the tag doesn't match the expected tag for this item,
280 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
281 * filled with 0 for this member.
282 * hasPointer, pointerOffset:
283 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
284 * the offset within the struct of the data pointer (or to the
285 * first data pointer, if more than one exist).
286 * size:
287 * Used by CRYPT_AsnDecodeSequence, not for your use.
289 struct AsnDecodeSequenceItem
291 BYTE tag;
292 DWORD offset;
293 InternalDecodeFunc decodeFunc;
294 DWORD minSize;
295 BOOL optional;
296 BOOL hasPointer;
297 DWORD pointerOffset;
298 DWORD size;
301 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
302 #define MEMBERSIZE(s, member, nextmember) \
303 (offsetof(s, nextmember) - offsetof(s, member))
305 /* Decodes the items in a sequence, where the items are described in items,
306 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
307 * pvStructInfo. nextData is a pointer to the memory location at which the
308 * first decoded item with a dynamic pointer should point.
309 * Upon decoding, *cbDecoded is the total number of bytes decoded.
310 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
312 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
313 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
314 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
316 BOOL ret;
317 DWORD i, decoded = 0;
318 const BYTE *ptr = pbEncoded;
320 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %p\n", items, cItem, pbEncoded,
321 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
323 for (i = 0, ret = TRUE; ret && i < cItem; i++)
325 if (cbEncoded - (ptr - pbEncoded) != 0)
327 DWORD itemLen;
329 if ((ret = CRYPT_GetLengthIndefinite(ptr,
330 cbEncoded - (ptr - pbEncoded), &itemLen)))
332 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
334 if (ptr[0] == items[i].tag || !items[i].tag)
336 DWORD itemEncodedLen;
338 if (itemLen == CMSG_INDEFINITE_LENGTH)
339 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
340 else
341 itemEncodedLen = 1 + itemLenBytes + itemLen;
342 if (nextData && pvStructInfo && items[i].hasPointer)
344 TRACE("Setting next pointer to %p\n",
345 nextData);
346 *(BYTE **)((BYTE *)pvStructInfo +
347 items[i].pointerOffset) = nextData;
349 if (items[i].decodeFunc)
351 DWORD itemDecoded;
353 if (pvStructInfo)
354 TRACE("decoding item %ld\n", i);
355 else
356 TRACE("sizing item %ld\n", i);
357 ret = items[i].decodeFunc(ptr, itemEncodedLen,
358 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
359 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
360 : NULL, &items[i].size, &itemDecoded);
361 if (ret)
363 if (items[i].size < items[i].minSize)
364 items[i].size = items[i].minSize;
365 else if (items[i].size > items[i].minSize)
367 /* Account for alignment padding */
368 items[i].size = ALIGN_DWORD_PTR(items[i].size);
370 TRACE("item %ld size: %ld\n", i, items[i].size);
371 if (nextData && items[i].hasPointer &&
372 items[i].size > items[i].minSize)
373 nextData += items[i].size - items[i].minSize;
374 if (itemDecoded > itemEncodedLen)
376 WARN("decoded length %ld exceeds encoded %ld\n",
377 itemDecoded, itemEncodedLen);
378 SetLastError(CRYPT_E_ASN1_CORRUPT);
379 ret = FALSE;
381 else
383 ptr += itemDecoded;
384 decoded += itemDecoded;
385 TRACE("item %ld: decoded %ld bytes\n", i,
386 itemDecoded);
389 else if (items[i].optional &&
390 GetLastError() == CRYPT_E_ASN1_BADTAG)
392 TRACE("skipping optional item %ld\n", i);
393 items[i].size = items[i].minSize;
394 SetLastError(NOERROR);
395 ret = TRUE;
397 else
398 TRACE("item %ld failed: %08lx\n", i,
399 GetLastError());
401 else if (itemLen == CMSG_INDEFINITE_LENGTH)
403 ERR("can't use indefinite length encoding without a decoder\n");
404 SetLastError(CRYPT_E_ASN1_CORRUPT);
405 ret = FALSE;
407 else
409 TRACE("item %ld: decoded %ld bytes\n", i, itemEncodedLen);
410 ptr += itemEncodedLen;
411 decoded += itemEncodedLen;
412 items[i].size = items[i].minSize;
415 else if (items[i].optional)
417 TRACE("skipping optional item %ld\n", i);
418 items[i].size = items[i].minSize;
420 else
422 TRACE("item %ld: tag %02x doesn't match expected %02x\n",
423 i, ptr[0], items[i].tag);
424 SetLastError(CRYPT_E_ASN1_BADTAG);
425 ret = FALSE;
429 else if (items[i].optional)
431 TRACE("missing optional item %ld, skipping\n", i);
432 items[i].size = items[i].minSize;
434 else
436 TRACE("not enough bytes for item %ld, failing\n", i);
437 SetLastError(CRYPT_E_ASN1_CORRUPT);
438 ret = FALSE;
441 if (cbDecoded)
442 *cbDecoded = decoded;
443 TRACE("returning %d\n", ret);
444 return ret;
447 /* This decodes an arbitrary sequence into a contiguous block of memory
448 * (basically, a struct.) Each element being decoded is described by a struct
449 * AsnDecodeSequenceItem, see above.
450 * startingPointer is an optional pointer to the first place where dynamic
451 * data will be stored. If you know the starting offset, you may pass it
452 * here. Otherwise, pass NULL, and one will be inferred from the items.
454 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
455 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
456 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
457 DWORD *pcbDecoded, void *startingPointer)
459 BOOL ret;
461 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded,
462 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
463 startingPointer);
465 if (!cbEncoded)
467 SetLastError(CRYPT_E_ASN1_EOD);
468 return FALSE;
470 if (pbEncoded[0] == ASN_SEQUENCE)
472 DWORD dataLen;
474 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
476 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
477 const BYTE *ptr = pbEncoded + 1 + lenBytes;
478 BOOL indefinite = FALSE;
480 cbEncoded -= 1 + lenBytes;
481 if (dataLen == CMSG_INDEFINITE_LENGTH)
483 dataLen = cbEncoded;
484 indefinite = TRUE;
485 lenBytes += 2;
487 else if (cbEncoded < dataLen)
489 TRACE("dataLen %ld exceeds cbEncoded %ld, failing\n", dataLen,
490 cbEncoded);
491 SetLastError(CRYPT_E_ASN1_CORRUPT);
492 ret = FALSE;
494 if (ret)
496 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
497 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
498 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
500 if (cbDecoded > cbEncoded - 2)
502 /* Not enough space for 0 TLV */
503 SetLastError(CRYPT_E_ASN1_CORRUPT);
504 ret = FALSE;
506 else if (*(ptr + cbDecoded) != 0 ||
507 *(ptr + cbDecoded + 1) != 0)
509 TRACE("expected 0 TLV\n");
510 SetLastError(CRYPT_E_ASN1_CORRUPT);
511 ret = FALSE;
513 else
514 cbDecoded += 2;
517 if (ret && !indefinite && cbDecoded != dataLen)
519 TRACE("expected %ld decoded, got %ld, failing\n", dataLen,
520 cbDecoded);
521 SetLastError(CRYPT_E_ASN1_CORRUPT);
522 ret = FALSE;
524 if (ret)
526 DWORD i, bytesNeeded = 0, structSize = 0;
528 for (i = 0; i < cItem; i++)
530 if (items[i].size > items[i].minSize)
531 bytesNeeded += items[i].size - items[i].minSize;
532 structSize = max( structSize, items[i].offset + items[i].minSize );
534 bytesNeeded += structSize;
535 if (pcbDecoded)
536 *pcbDecoded = 1 + lenBytes + cbDecoded;
537 if (!pvStructInfo)
538 *pcbStructInfo = bytesNeeded;
539 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
540 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
542 BYTE *nextData;
544 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
545 pvStructInfo = *(BYTE **)pvStructInfo;
546 if (startingPointer)
547 nextData = startingPointer;
548 else
549 nextData = (BYTE *)pvStructInfo + structSize;
550 memset(pvStructInfo, 0, structSize);
551 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
552 ptr, dataLen, dwFlags, pvStructInfo, nextData,
553 &cbDecoded);
554 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
555 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
560 else
562 SetLastError(CRYPT_E_ASN1_BADTAG);
563 ret = FALSE;
565 TRACE("returning %d (%08lx)\n", ret, GetLastError());
566 return ret;
569 /* tag:
570 * The expected tag of the entire encoded array (usually a variant
571 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
572 * regardless of the tag seen.
573 * countOffset:
574 * The offset within the outer structure at which the count exists.
575 * For example, a structure such as CRYPT_ATTRIBUTES has countOffset == 0,
576 * while CRYPT_ATTRIBUTE has countOffset ==
577 * offsetof(CRYPT_ATTRIBUTE, cValue).
578 * arrayOffset:
579 * The offset within the outer structure at which the array pointer exists.
580 * For example, CRYPT_ATTRIBUTES has arrayOffset ==
581 * offsetof(CRYPT_ATTRIBUTES, rgAttr).
582 * minArraySize:
583 * The minimum size of the decoded array. On WIN32, this is always 8:
584 * sizeof(DWORD) + sizeof(void *). On WIN64, it can be larger due to
585 * alignment.
586 * decodeFunc:
587 * used to decode each item in the array
588 * itemSize:
589 * is the minimum size of each decoded item
590 * hasPointer:
591 * indicates whether each item has a dynamic pointer
592 * pointerOffset:
593 * indicates the offset within itemSize at which the pointer exists
595 struct AsnArrayDescriptor
597 BYTE tag;
598 DWORD countOffset;
599 DWORD arrayOffset;
600 DWORD minArraySize;
601 InternalDecodeFunc decodeFunc;
602 DWORD itemSize;
603 BOOL hasPointer;
604 DWORD pointerOffset;
607 struct AsnArrayItemSize
609 DWORD encodedLen;
610 DWORD size;
613 /* Decodes an array of like types into a structure described by a struct
614 * AsnArrayDescriptor.
616 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
617 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
618 const CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
619 DWORD *pcbDecoded)
621 BOOL ret = TRUE;
623 TRACE("%p, %p, %ld, %p, %ld\n", arrayDesc, pbEncoded,
624 cbEncoded, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
626 if (!cbEncoded)
628 SetLastError(CRYPT_E_ASN1_EOD);
629 ret = FALSE;
631 else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
633 DWORD dataLen;
635 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
637 DWORD bytesNeeded = arrayDesc->minArraySize, cItems = 0, capacity = 0, decoded;
638 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
639 /* There can be arbitrarily many items, but there is often only one.
641 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
643 decoded = 1 + lenBytes;
644 if (dataLen)
646 const BYTE *ptr;
647 BOOL doneDecoding = FALSE;
649 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
651 if (dataLen == CMSG_INDEFINITE_LENGTH)
653 if (ptr[0] == 0)
655 doneDecoding = TRUE;
656 if (ptr[1] != 0)
658 SetLastError(CRYPT_E_ASN1_CORRUPT);
659 ret = FALSE;
661 else
662 decoded += 2;
665 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
666 doneDecoding = TRUE;
667 if (!doneDecoding)
669 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
671 /* Each item decoded may not tolerate extraneous bytes,
672 * so get the length of the next element if known.
674 if ((ret = CRYPT_GetLengthIndefinite(ptr,
675 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
677 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
678 itemEncoded = cbEncoded - (ptr - pbEncoded);
679 else
680 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
681 itemDataLen;
683 if (ret)
684 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
685 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
686 &itemDecoded);
687 if (ret)
689 /* Ignore an item that failed to decode but the decoder doesn't want to fail the whole process */
690 if (!size)
692 ptr += itemEncoded;
693 continue;
696 if (++cItems <= 1)
697 itemSizes = &itemSize;
698 else if (itemSizes == &itemSize)
700 capacity = 1024;
701 itemSizes = CryptMemAlloc(capacity * sizeof(struct AsnArrayItemSize));
702 if (itemSizes) *itemSizes = itemSize;
704 else if (cItems > capacity)
706 capacity = capacity * 3 / 2;
707 itemSizes = CryptMemRealloc(itemSizes, capacity * sizeof(struct AsnArrayItemSize));
709 if (itemSizes)
711 decoded += itemDecoded;
712 itemSizes[cItems - 1].encodedLen = itemEncoded;
713 itemSizes[cItems - 1].size = size;
714 bytesNeeded += size;
715 ptr += itemEncoded;
717 else
718 ret = FALSE;
723 if (ret)
725 if (pcbDecoded)
726 *pcbDecoded = decoded;
727 if (!pvStructInfo)
728 *pcbStructInfo = bytesNeeded;
729 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
730 pvStructInfo, pcbStructInfo, bytesNeeded)))
732 DWORD i, *pcItems;
733 BYTE *nextData;
734 const BYTE *ptr;
735 void *rgItems;
737 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
738 pvStructInfo = *(void **)pvStructInfo;
739 pcItems = pvStructInfo;
740 *pcItems = cItems;
741 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
743 rgItems = (BYTE *)pvStructInfo +
744 arrayDesc->minArraySize;
745 *(void **)((BYTE *)pcItems -
746 arrayDesc->countOffset + arrayDesc->arrayOffset) =
747 rgItems;
749 else
750 rgItems = *(void **)((BYTE *)pcItems -
751 arrayDesc->countOffset + arrayDesc->arrayOffset);
752 nextData = (BYTE *)rgItems + cItems * arrayDesc->itemSize;
753 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
754 i < cItems && ptr - pbEncoded - 1 - lenBytes <
755 dataLen; i++)
757 DWORD itemDecoded;
759 if (arrayDesc->hasPointer)
760 *(BYTE **)((BYTE *)rgItems + i * arrayDesc->itemSize
761 + arrayDesc->pointerOffset) = nextData;
762 ret = arrayDesc->decodeFunc(ptr,
763 itemSizes[i].encodedLen,
764 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
765 (BYTE *)rgItems + i * arrayDesc->itemSize,
766 &itemSizes[i].size, &itemDecoded);
767 if (ret)
769 nextData += itemSizes[i].size - arrayDesc->itemSize;
770 ptr += itemDecoded;
773 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
774 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
777 if (itemSizes != &itemSize)
778 CryptMemFree(itemSizes);
781 else
783 SetLastError(CRYPT_E_ASN1_BADTAG);
784 ret = FALSE;
786 return ret;
789 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
790 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
791 * to CRYPT_E_ASN1_CORRUPT.
792 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
793 * set!
795 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
796 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
798 BOOL ret;
799 DWORD dataLen;
801 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
803 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
804 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
806 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
807 bytesNeeded += 1 + lenBytes + dataLen;
809 if (pcbDecoded)
810 *pcbDecoded = 1 + lenBytes + dataLen;
811 if (!pvStructInfo)
812 *pcbStructInfo = bytesNeeded;
813 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
815 CRYPT_DER_BLOB *blob;
817 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
818 pvStructInfo = *(BYTE **)pvStructInfo;
819 blob = pvStructInfo;
820 blob->cbData = 1 + lenBytes + dataLen;
821 if (blob->cbData)
823 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
824 blob->pbData = (BYTE *)pbEncoded;
825 else
827 assert(blob->pbData);
828 memcpy(blob->pbData, pbEncoded, blob->cbData);
831 else
833 SetLastError(CRYPT_E_ASN1_CORRUPT);
834 ret = FALSE;
838 return ret;
841 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
842 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
843 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
844 DWORD *pcbDecoded)
846 BOOL ret;
848 TRACE("(%p, %ld, 0x%08lx, %p, %ld, %p)\n", pbEncoded, cbEncoded, dwFlags,
849 pvStructInfo, *pcbStructInfo, pcbDecoded);
851 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
852 * place.
854 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
855 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
856 pcbDecoded);
857 if (ret && pvStructInfo)
859 CRYPT_BIT_BLOB *blob = pvStructInfo;
861 if (blob->cbData)
863 DWORD i;
864 BYTE temp;
866 for (i = 0; i < blob->cbData / 2; i++)
868 temp = blob->pbData[i];
869 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
870 blob->pbData[blob->cbData - i - 1] = temp;
874 TRACE("returning %d (%08lx)\n", ret, GetLastError());
875 return ret;
878 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
879 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
880 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
882 BOOL ret = TRUE;
884 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
885 pDecodePara, pvStructInfo, *pcbStructInfo);
887 __TRY
889 struct AsnDecodeSequenceItem items[] = {
890 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
891 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
892 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
893 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
894 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
895 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
896 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
897 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
898 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
899 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
902 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
903 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
904 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
905 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
906 pcbStructInfo, NULL, NULL);
908 __EXCEPT_PAGE_FAULT
910 SetLastError(STATUS_ACCESS_VIOLATION);
911 ret = FALSE;
913 __ENDTRY
915 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
916 return ret;
919 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
920 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
922 BOOL ret;
923 DWORD dataLen;
925 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
927 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
929 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
930 dwFlags, pvStructInfo, pcbStructInfo, NULL);
931 if (pcbDecoded)
932 *pcbDecoded = 1 + lenBytes + dataLen;
934 return ret;
937 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
938 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
940 BOOL ret;
942 struct AsnDecodeSequenceItem items[] = {
943 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
944 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
945 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
946 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
949 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
950 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
951 pcbDecoded, NULL);
952 return ret;
955 static BOOL CRYPT_AsnDecodeCertExtensionsInternal(const BYTE *pbEncoded,
956 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
957 DWORD *pcbDecoded)
959 BOOL ret = TRUE;
960 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
961 offsetof(CERT_INFO, cExtension), offsetof(CERT_INFO, rgExtension),
962 FINALMEMBERSIZE(CERT_INFO, cExtension),
963 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
964 offsetof(CERT_EXTENSION, pszObjId) };
966 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
967 pvStructInfo, *pcbStructInfo, pcbDecoded);
969 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
970 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
971 return ret;
974 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
975 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
976 DWORD *pcbDecoded)
978 BOOL ret;
979 DWORD dataLen;
981 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
983 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
985 ret = CRYPT_AsnDecodeCertExtensionsInternal(pbEncoded + 1 + lenBytes,
986 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
987 if (ret && pcbDecoded)
988 *pcbDecoded = 1 + lenBytes + dataLen;
990 return ret;
993 static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
994 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
995 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
997 BOOL ret = TRUE;
998 struct AsnDecodeSequenceItem items[] = {
999 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
1000 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1001 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
1002 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
1003 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
1004 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
1005 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1006 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
1007 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1008 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1009 Issuer.pbData) },
1010 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
1011 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
1012 FALSE, 0 },
1013 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
1014 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1015 Subject.pbData) },
1016 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
1017 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
1018 FALSE, TRUE, offsetof(CERT_INFO,
1019 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
1020 { ASN_CONTEXT | 1, offsetof(CERT_INFO, IssuerUniqueId),
1021 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1022 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
1023 { ASN_CONTEXT | 2, offsetof(CERT_INFO, SubjectUniqueId),
1024 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1025 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
1026 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
1027 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(CERT_INFO, cExtension),
1028 TRUE, TRUE, offsetof(CERT_INFO, rgExtension), 0 },
1031 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1032 pDecodePara, pvStructInfo, *pcbStructInfo);
1034 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1035 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1036 NULL, NULL);
1037 if (ret && pvStructInfo)
1039 CERT_INFO *info;
1041 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1042 info = *(CERT_INFO **)pvStructInfo;
1043 else
1044 info = pvStructInfo;
1045 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1046 !info->Subject.cbData)
1048 SetLastError(CRYPT_E_ASN1_CORRUPT);
1049 /* Don't need to deallocate, because it should have failed on the
1050 * first pass (and no memory was allocated.)
1052 ret = FALSE;
1056 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1057 return ret;
1060 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1061 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1062 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1064 BOOL ret = FALSE;
1066 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1067 pDecodePara, pvStructInfo, *pcbStructInfo);
1069 __TRY
1071 DWORD size = 0;
1073 /* Unless told not to, first try to decode it as a signed cert. */
1074 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1076 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1078 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1079 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1080 &signedCert, &size);
1081 if (ret)
1083 size = 0;
1084 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1085 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1086 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1087 pvStructInfo, pcbStructInfo);
1088 LocalFree(signedCert);
1091 /* Failing that, try it as an unsigned cert */
1092 if (!ret)
1094 size = 0;
1095 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1096 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1097 pDecodePara, pvStructInfo, pcbStructInfo);
1100 __EXCEPT_PAGE_FAULT
1102 SetLastError(STATUS_ACCESS_VIOLATION);
1104 __ENDTRY
1106 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1107 return ret;
1110 static BOOL CRYPT_AsnDecodeCRLEntryExtensions(const BYTE *pbEncoded,
1111 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1112 DWORD *pcbDecoded)
1114 BOOL ret = TRUE;
1115 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1116 offsetof(CRL_ENTRY, cExtension), offsetof(CRL_ENTRY, rgExtension),
1117 FINALMEMBERSIZE(CRL_ENTRY, cExtension),
1118 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1119 offsetof(CERT_EXTENSION, pszObjId) };
1121 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
1122 pvStructInfo, *pcbStructInfo, pcbDecoded);
1124 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1125 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1126 return ret;
1129 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1130 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1132 BOOL ret;
1133 struct AsnDecodeSequenceItem items[] = {
1134 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1135 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1136 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1137 { 0, offsetof(CRL_ENTRY, RevocationDate),
1138 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1139 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1140 CRYPT_AsnDecodeCRLEntryExtensions,
1141 FINALMEMBERSIZE(CRL_ENTRY, cExtension), TRUE, TRUE,
1142 offsetof(CRL_ENTRY, rgExtension), 0 },
1144 PCRL_ENTRY entry = pvStructInfo;
1146 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
1147 *pcbStructInfo);
1149 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1150 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1151 entry ? entry->SerialNumber.pbData : NULL);
1152 if (ret && entry && !entry->SerialNumber.cbData)
1154 WARN("empty CRL entry serial number\n");
1155 SetLastError(CRYPT_E_ASN1_CORRUPT);
1156 ret = FALSE;
1158 return ret;
1161 /* Warning: assumes pvStructInfo points to the cCRLEntry member of a CRL_INFO
1162 * whose rgCRLEntry member has been set prior to calling.
1164 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1165 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1167 BOOL ret;
1168 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1169 offsetof(CRL_INFO, cCRLEntry), offsetof(CRL_INFO, rgCRLEntry),
1170 MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1171 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1172 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1174 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
1175 pvStructInfo, *pcbStructInfo, pcbDecoded);
1177 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1178 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1179 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1180 return ret;
1183 static BOOL CRYPT_AsnDecodeCRLExtensionsInternal(const BYTE *pbEncoded,
1184 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1185 DWORD *pcbDecoded)
1187 BOOL ret = TRUE;
1188 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1189 offsetof(CRL_INFO, cExtension), offsetof(CRL_INFO, rgExtension),
1190 FINALMEMBERSIZE(CRL_INFO, cExtension),
1191 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1192 offsetof(CERT_EXTENSION, pszObjId) };
1194 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
1195 pvStructInfo, *pcbStructInfo, pcbDecoded);
1197 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1198 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1199 return ret;
1202 static BOOL CRYPT_AsnDecodeCRLExtensions(const BYTE *pbEncoded,
1203 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1204 DWORD *pcbDecoded)
1206 BOOL ret;
1207 DWORD dataLen;
1209 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1211 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1213 ret = CRYPT_AsnDecodeCRLExtensionsInternal(pbEncoded + 1 + lenBytes,
1214 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
1215 if (ret && pcbDecoded)
1216 *pcbDecoded = 1 + lenBytes + dataLen;
1218 return ret;
1221 static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1222 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1223 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1225 struct AsnDecodeSequenceItem items[] = {
1226 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1227 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1228 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1229 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1230 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1231 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1232 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1233 Issuer.pbData) },
1234 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1235 sizeof(FILETIME), FALSE, FALSE, 0 },
1236 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1237 sizeof(FILETIME), TRUE, FALSE, 0 },
1238 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1239 CRYPT_AsnDecodeCRLEntries, MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1240 TRUE, TRUE, offsetof(CRL_INFO, rgCRLEntry), 0 },
1241 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1242 CRYPT_AsnDecodeCRLExtensions, FINALMEMBERSIZE(CRL_INFO, cExtension),
1243 TRUE, TRUE, offsetof(CRL_INFO, rgExtension), 0 },
1245 BOOL ret = TRUE;
1247 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1248 pDecodePara, pvStructInfo, *pcbStructInfo);
1250 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags,
1251 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1253 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1254 return ret;
1257 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1258 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1259 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1261 BOOL ret = FALSE;
1263 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1264 pDecodePara, pvStructInfo, *pcbStructInfo);
1266 __TRY
1268 DWORD size = 0;
1270 /* Unless told not to, first try to decode it as a signed crl. */
1271 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1273 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1275 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1276 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1277 &signedCrl, &size);
1278 if (ret)
1280 size = 0;
1281 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1282 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1283 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1284 pvStructInfo, pcbStructInfo);
1285 LocalFree(signedCrl);
1288 /* Failing that, try it as an unsigned crl */
1289 if (!ret)
1291 size = 0;
1292 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1293 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1294 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1297 __EXCEPT_PAGE_FAULT
1299 SetLastError(STATUS_ACCESS_VIOLATION);
1301 __ENDTRY
1303 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1304 return ret;
1307 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1308 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1310 BOOL ret = TRUE;
1311 DWORD dataLen;
1313 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1314 pvStructInfo, *pcbStructInfo);
1316 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1318 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1319 DWORD bytesNeeded = sizeof(LPSTR);
1321 if (dataLen)
1323 const BYTE *ptr;
1324 char str[32];
1326 snprintf(str, sizeof(str), "%d.%d",
1327 pbEncoded[1 + lenBytes] / 40,
1328 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1329 * 40);
1330 bytesNeeded += strlen(str) + 1;
1331 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1332 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1334 int val = 0;
1336 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1337 (*ptr & 0x80))
1339 val <<= 7;
1340 val |= *ptr & 0x7f;
1341 ptr++;
1343 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1344 (*ptr & 0x80))
1346 SetLastError(CRYPT_E_ASN1_CORRUPT);
1347 ret = FALSE;
1349 else
1351 val <<= 7;
1352 val |= *ptr++;
1353 snprintf(str, sizeof(str), ".%d", val);
1354 bytesNeeded += strlen(str);
1358 if (pcbDecoded)
1359 *pcbDecoded = 1 + lenBytes + dataLen;
1360 if (!pvStructInfo)
1361 *pcbStructInfo = bytesNeeded;
1362 else if (*pcbStructInfo < bytesNeeded)
1364 *pcbStructInfo = bytesNeeded;
1365 SetLastError(ERROR_MORE_DATA);
1366 ret = FALSE;
1368 else
1370 if (dataLen)
1372 const BYTE *ptr;
1373 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1375 *pszObjId = 0;
1376 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1377 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1378 40) * 40);
1379 pszObjId += strlen(pszObjId);
1380 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1381 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1383 int val = 0;
1385 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1386 (*ptr & 0x80))
1388 val <<= 7;
1389 val |= *ptr & 0x7f;
1390 ptr++;
1392 val <<= 7;
1393 val |= *ptr++;
1394 sprintf(pszObjId, ".%d", val);
1395 pszObjId += strlen(pszObjId);
1398 else
1399 *(LPSTR *)pvStructInfo = NULL;
1400 *pcbStructInfo = bytesNeeded;
1403 return ret;
1406 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1407 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1409 BOOL ret;
1411 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1412 pvStructInfo, *pcbStructInfo);
1414 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1415 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1416 pvStructInfo, pcbStructInfo, pcbDecoded);
1417 else
1419 SetLastError(CRYPT_E_ASN1_BADTAG);
1420 ret = FALSE;
1422 return ret;
1425 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1426 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1428 struct AsnDecodeSequenceItem items[] = {
1429 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1430 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1431 offsetof(CERT_EXTENSION, pszObjId), 0 },
1432 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1433 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1434 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1435 CRYPT_AsnDecodeOctets, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1436 offsetof(CERT_EXTENSION, Value.pbData) },
1438 BOOL ret = TRUE;
1439 PCERT_EXTENSION ext = pvStructInfo;
1441 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
1442 *pcbStructInfo);
1444 if (ext)
1445 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1446 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1447 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1448 pcbDecoded, ext ? ext->pszObjId : NULL);
1449 if (ext)
1450 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1451 debugstr_a(ext->pszObjId));
1452 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1453 return ret;
1456 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1457 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1458 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1460 BOOL ret = TRUE;
1462 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1463 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
1465 __TRY
1467 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1468 offsetof(CERT_EXTENSIONS, cExtension),
1469 offsetof(CERT_EXTENSIONS, rgExtension),
1470 sizeof(CERT_EXTENSIONS),
1471 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1472 offsetof(CERT_EXTENSION, pszObjId) };
1473 CERT_EXTENSIONS *exts = pvStructInfo;
1475 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1476 exts->rgExtension = (CERT_EXTENSION *)(exts + 1);
1477 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1478 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1480 __EXCEPT_PAGE_FAULT
1482 SetLastError(STATUS_ACCESS_VIOLATION);
1483 ret = FALSE;
1485 __ENDTRY
1486 return ret;
1489 /* Warning: this assumes the address of value->Value.pbData is already set, in
1490 * order to avoid overwriting memory. (In some cases, it may change it, if it
1491 * doesn't copy anything to memory.) Be sure to set it correctly!
1493 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1494 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1495 DWORD *pcbDecoded)
1497 BOOL ret = TRUE;
1498 DWORD dataLen;
1499 CERT_NAME_VALUE *value = pvStructInfo;
1501 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1503 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1504 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1506 switch (pbEncoded[0])
1508 case ASN_OCTETSTRING:
1509 valueType = CERT_RDN_OCTET_STRING;
1510 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1511 bytesNeeded += dataLen;
1512 break;
1513 case ASN_NUMERICSTRING:
1514 valueType = CERT_RDN_NUMERIC_STRING;
1515 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1516 bytesNeeded += dataLen;
1517 break;
1518 case ASN_PRINTABLESTRING:
1519 valueType = CERT_RDN_PRINTABLE_STRING;
1520 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1521 bytesNeeded += dataLen;
1522 break;
1523 case ASN_IA5STRING:
1524 valueType = CERT_RDN_IA5_STRING;
1525 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1526 bytesNeeded += dataLen;
1527 break;
1528 case ASN_T61STRING:
1529 valueType = CERT_RDN_T61_STRING;
1530 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1531 bytesNeeded += dataLen;
1532 break;
1533 case ASN_VIDEOTEXSTRING:
1534 valueType = CERT_RDN_VIDEOTEX_STRING;
1535 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1536 bytesNeeded += dataLen;
1537 break;
1538 case ASN_GRAPHICSTRING:
1539 valueType = CERT_RDN_GRAPHIC_STRING;
1540 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1541 bytesNeeded += dataLen;
1542 break;
1543 case ASN_VISIBLESTRING:
1544 valueType = CERT_RDN_VISIBLE_STRING;
1545 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1546 bytesNeeded += dataLen;
1547 break;
1548 case ASN_GENERALSTRING:
1549 valueType = CERT_RDN_GENERAL_STRING;
1550 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1551 bytesNeeded += dataLen;
1552 break;
1553 case ASN_UNIVERSALSTRING:
1554 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1555 SetLastError(CRYPT_E_ASN1_BADTAG);
1556 return FALSE;
1557 case ASN_BMPSTRING:
1558 valueType = CERT_RDN_BMP_STRING;
1559 bytesNeeded += dataLen;
1560 break;
1561 case ASN_UTF8STRING:
1562 valueType = CERT_RDN_UTF8_STRING;
1563 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1564 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * sizeof(WCHAR);
1565 break;
1566 default:
1567 SetLastError(CRYPT_E_ASN1_BADTAG);
1568 return FALSE;
1571 if (pcbDecoded)
1572 *pcbDecoded = 1 + lenBytes + dataLen;
1573 if (!value)
1574 *pcbStructInfo = bytesNeeded;
1575 else if (*pcbStructInfo < bytesNeeded)
1577 *pcbStructInfo = bytesNeeded;
1578 SetLastError(ERROR_MORE_DATA);
1579 ret = FALSE;
1581 else
1583 *pcbStructInfo = bytesNeeded;
1584 value->dwValueType = valueType;
1585 if (dataLen)
1587 DWORD i;
1589 assert(value->Value.pbData);
1590 switch (pbEncoded[0])
1592 case ASN_OCTETSTRING:
1593 case ASN_NUMERICSTRING:
1594 case ASN_PRINTABLESTRING:
1595 case ASN_IA5STRING:
1596 case ASN_T61STRING:
1597 case ASN_VIDEOTEXSTRING:
1598 case ASN_GRAPHICSTRING:
1599 case ASN_VISIBLESTRING:
1600 case ASN_GENERALSTRING:
1601 value->Value.cbData = dataLen;
1602 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1603 memcpy(value->Value.pbData,
1604 pbEncoded + 1 + lenBytes, dataLen);
1605 else
1606 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1607 lenBytes;
1608 break;
1609 case ASN_BMPSTRING:
1611 LPWSTR str = (LPWSTR)value->Value.pbData;
1613 value->Value.cbData = dataLen;
1614 for (i = 0; i < dataLen / 2; i++)
1615 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1616 pbEncoded[1 + lenBytes + 2 * i + 1];
1617 break;
1619 case ASN_UTF8STRING:
1621 LPWSTR str = (LPWSTR)value->Value.pbData;
1623 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1624 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1625 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1626 break;
1630 else
1632 value->Value.cbData = 0;
1633 value->Value.pbData = NULL;
1637 return ret;
1640 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1641 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1642 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1644 BOOL ret = TRUE;
1646 __TRY
1648 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1649 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1650 if (ret && pvStructInfo)
1652 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1653 pcbStructInfo, *pcbStructInfo);
1654 if (ret)
1656 CERT_NAME_VALUE *value;
1658 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1659 pvStructInfo = *(BYTE **)pvStructInfo;
1660 value = pvStructInfo;
1661 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1662 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1663 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1664 pcbStructInfo, NULL);
1665 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1666 CRYPT_FreeSpace(pDecodePara, value);
1670 __EXCEPT_PAGE_FAULT
1672 SetLastError(STATUS_ACCESS_VIOLATION);
1673 ret = FALSE;
1675 __ENDTRY
1676 return ret;
1679 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1680 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1681 DWORD *pcbDecoded)
1683 BOOL ret = TRUE;
1684 DWORD dataLen;
1685 CERT_NAME_VALUE *value = pvStructInfo;
1687 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1689 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1690 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1692 switch (pbEncoded[0])
1694 case ASN_NUMERICSTRING:
1695 valueType = CERT_RDN_NUMERIC_STRING;
1696 if (dataLen)
1697 bytesNeeded += (dataLen + 1) * 2;
1698 break;
1699 case ASN_PRINTABLESTRING:
1700 valueType = CERT_RDN_PRINTABLE_STRING;
1701 if (dataLen)
1702 bytesNeeded += (dataLen + 1) * 2;
1703 break;
1704 case ASN_IA5STRING:
1705 valueType = CERT_RDN_IA5_STRING;
1706 if (dataLen)
1707 bytesNeeded += (dataLen + 1) * 2;
1708 break;
1709 case ASN_T61STRING:
1710 valueType = CERT_RDN_T61_STRING;
1711 if (dataLen)
1712 bytesNeeded += (dataLen + 1) * 2;
1713 break;
1714 case ASN_VIDEOTEXSTRING:
1715 valueType = CERT_RDN_VIDEOTEX_STRING;
1716 if (dataLen)
1717 bytesNeeded += (dataLen + 1) * 2;
1718 break;
1719 case ASN_GRAPHICSTRING:
1720 valueType = CERT_RDN_GRAPHIC_STRING;
1721 if (dataLen)
1722 bytesNeeded += (dataLen + 1) * 2;
1723 break;
1724 case ASN_VISIBLESTRING:
1725 valueType = CERT_RDN_VISIBLE_STRING;
1726 if (dataLen)
1727 bytesNeeded += (dataLen + 1) * 2;
1728 break;
1729 case ASN_GENERALSTRING:
1730 valueType = CERT_RDN_GENERAL_STRING;
1731 if (dataLen)
1732 bytesNeeded += (dataLen + 1) * 2;
1733 break;
1734 case ASN_UNIVERSALSTRING:
1735 valueType = CERT_RDN_UNIVERSAL_STRING;
1736 if (dataLen)
1737 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
1738 break;
1739 case ASN_BMPSTRING:
1740 valueType = CERT_RDN_BMP_STRING;
1741 if (dataLen)
1742 bytesNeeded += dataLen + sizeof(WCHAR);
1743 break;
1744 case ASN_UTF8STRING:
1745 valueType = CERT_RDN_UTF8_STRING;
1746 if (dataLen)
1747 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
1748 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
1749 break;
1750 default:
1751 SetLastError(CRYPT_E_ASN1_BADTAG);
1752 return FALSE;
1755 if (pcbDecoded)
1756 *pcbDecoded = 1 + lenBytes + dataLen;
1757 if (!value)
1758 *pcbStructInfo = bytesNeeded;
1759 else if (*pcbStructInfo < bytesNeeded)
1761 *pcbStructInfo = bytesNeeded;
1762 SetLastError(ERROR_MORE_DATA);
1763 ret = FALSE;
1765 else
1767 *pcbStructInfo = bytesNeeded;
1768 value->dwValueType = valueType;
1769 if (dataLen)
1771 DWORD i;
1772 LPWSTR str = (LPWSTR)value->Value.pbData;
1774 assert(value->Value.pbData);
1775 switch (pbEncoded[0])
1777 case ASN_NUMERICSTRING:
1778 case ASN_PRINTABLESTRING:
1779 case ASN_IA5STRING:
1780 case ASN_T61STRING:
1781 case ASN_VIDEOTEXSTRING:
1782 case ASN_GRAPHICSTRING:
1783 case ASN_VISIBLESTRING:
1784 case ASN_GENERALSTRING:
1785 value->Value.cbData = dataLen * 2;
1786 for (i = 0; i < dataLen; i++)
1787 str[i] = pbEncoded[1 + lenBytes + i];
1788 str[i] = 0;
1789 break;
1790 case ASN_UNIVERSALSTRING:
1791 value->Value.cbData = dataLen / 2;
1792 for (i = 0; i < dataLen / 4; i++)
1793 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1794 | pbEncoded[1 + lenBytes + 2 * i + 3];
1795 str[i] = 0;
1796 break;
1797 case ASN_BMPSTRING:
1798 value->Value.cbData = dataLen;
1799 for (i = 0; i < dataLen / 2; i++)
1800 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1801 pbEncoded[1 + lenBytes + 2 * i + 1];
1802 str[i] = 0;
1803 break;
1804 case ASN_UTF8STRING:
1805 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1806 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1807 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR);
1808 *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0;
1809 value->Value.cbData += sizeof(WCHAR);
1810 break;
1813 else
1815 value->Value.cbData = 0;
1816 value->Value.pbData = NULL;
1820 return ret;
1823 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1824 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1825 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1827 BOOL ret = TRUE;
1829 __TRY
1831 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1832 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1833 if (ret && pvStructInfo)
1835 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1836 pcbStructInfo, *pcbStructInfo);
1837 if (ret)
1839 CERT_NAME_VALUE *value;
1841 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1842 pvStructInfo = *(BYTE **)pvStructInfo;
1843 value = pvStructInfo;
1844 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1845 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1846 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1847 pcbStructInfo, NULL);
1848 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1849 CRYPT_FreeSpace(pDecodePara, value);
1853 __EXCEPT_PAGE_FAULT
1855 SetLastError(STATUS_ACCESS_VIOLATION);
1856 ret = FALSE;
1858 __ENDTRY
1859 return ret;
1862 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1863 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1865 BOOL ret;
1866 struct AsnDecodeSequenceItem items[] = {
1867 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1868 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1869 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1870 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1871 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1872 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1874 CERT_RDN_ATTR *attr = pvStructInfo;
1876 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1877 pvStructInfo, *pcbStructInfo);
1879 if (attr)
1880 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1881 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1882 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1883 attr ? attr->pszObjId : NULL);
1884 if (attr)
1886 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1887 debugstr_a(attr->pszObjId));
1888 TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1890 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1891 return ret;
1894 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1895 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1897 BOOL ret = TRUE;
1898 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1899 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1900 sizeof(CERT_RDN),
1901 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1902 offsetof(CERT_RDN_ATTR, pszObjId) };
1904 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1905 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1906 return ret;
1909 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1910 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1911 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1913 BOOL ret = TRUE;
1915 __TRY
1917 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1918 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
1919 sizeof(CERT_NAME_INFO),
1920 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1921 offsetof(CERT_RDN, rgRDNAttr) };
1922 DWORD bytesNeeded = 0;
1924 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1925 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
1926 NULL);
1927 if (ret)
1929 if (!pvStructInfo)
1930 *pcbStructInfo = bytesNeeded;
1931 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1932 pvStructInfo, pcbStructInfo, bytesNeeded)))
1934 CERT_NAME_INFO *info;
1936 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1937 pvStructInfo = *(BYTE **)pvStructInfo;
1938 info = pvStructInfo;
1939 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
1940 sizeof(CERT_NAME_INFO));
1941 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1942 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1943 &bytesNeeded, NULL);
1944 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1945 CRYPT_FreeSpace(pDecodePara, info);
1949 __EXCEPT_PAGE_FAULT
1951 SetLastError(STATUS_ACCESS_VIOLATION);
1952 ret = FALSE;
1954 __ENDTRY
1955 return ret;
1958 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1959 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1960 DWORD *pcbDecoded)
1962 BOOL ret;
1963 struct AsnDecodeSequenceItem items[] = {
1964 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1965 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1966 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1967 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1968 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1969 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1971 CERT_RDN_ATTR *attr = pvStructInfo;
1973 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1974 pvStructInfo, *pcbStructInfo);
1976 if (attr)
1977 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1978 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1979 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1980 attr ? attr->pszObjId : NULL);
1981 if (attr)
1983 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1984 debugstr_a(attr->pszObjId));
1985 TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1987 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1988 return ret;
1991 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1992 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1994 BOOL ret = TRUE;
1995 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1996 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1997 sizeof(CERT_RDN),
1998 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1999 offsetof(CERT_RDN_ATTR, pszObjId) };
2001 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2002 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2003 return ret;
2006 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
2007 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2008 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2010 BOOL ret = TRUE;
2012 __TRY
2014 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2015 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
2016 sizeof(CERT_NAME_INFO),
2017 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
2018 offsetof(CERT_RDN, rgRDNAttr) };
2019 DWORD bytesNeeded = 0;
2021 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2022 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
2023 NULL);
2024 if (ret)
2026 if (!pvStructInfo)
2027 *pcbStructInfo = bytesNeeded;
2028 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2029 pvStructInfo, pcbStructInfo, bytesNeeded)))
2031 CERT_NAME_INFO *info;
2033 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2034 pvStructInfo = *(BYTE **)pvStructInfo;
2035 info = pvStructInfo;
2036 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
2037 sizeof(CERT_NAME_INFO));
2038 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2039 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2040 &bytesNeeded, NULL);
2041 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2042 CRYPT_FreeSpace(pDecodePara, info);
2046 __EXCEPT_PAGE_FAULT
2048 SetLastError(STATUS_ACCESS_VIOLATION);
2049 ret = FALSE;
2051 __ENDTRY
2052 return ret;
2055 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
2056 DWORD *pcbDecoded)
2058 BOOL ret = TRUE, done = FALSE;
2059 DWORD indefiniteNestingLevels = 0, decoded = 0;
2061 TRACE("(%p, %ld)\n", pbEncoded, cbEncoded);
2063 do {
2064 DWORD dataLen;
2066 if (!cbEncoded)
2067 done = TRUE;
2068 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
2069 &dataLen)))
2071 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2073 if (dataLen == CMSG_INDEFINITE_LENGTH)
2075 indefiniteNestingLevels++;
2076 pbEncoded += 1 + lenBytes;
2077 cbEncoded -= 1 + lenBytes;
2078 decoded += 1 + lenBytes;
2079 TRACE("indefiniteNestingLevels = %ld\n",
2080 indefiniteNestingLevels);
2082 else
2084 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
2085 indefiniteNestingLevels)
2087 indefiniteNestingLevels--;
2088 TRACE("indefiniteNestingLevels = %ld\n",
2089 indefiniteNestingLevels);
2091 pbEncoded += 1 + lenBytes + dataLen;
2092 cbEncoded -= 1 + lenBytes + dataLen;
2093 decoded += 1 + lenBytes + dataLen;
2094 if (!indefiniteNestingLevels)
2095 done = TRUE;
2098 } while (ret && !done);
2099 /* If we haven't found all 0 TLVs, we haven't found the end */
2100 if (ret && indefiniteNestingLevels)
2102 SetLastError(CRYPT_E_ASN1_EOD);
2103 ret = FALSE;
2105 if (ret)
2106 *pcbDecoded = decoded;
2107 TRACE("returning %d (%ld)\n", ret, ret ? *pcbDecoded : 0);
2108 return ret;
2111 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
2112 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2113 DWORD *pcbDecoded)
2115 BOOL ret = TRUE;
2116 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
2118 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2119 pvStructInfo, *pcbStructInfo);
2121 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
2123 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2124 bytesNeeded += encodedLen;
2125 if (!pvStructInfo)
2126 *pcbStructInfo = bytesNeeded;
2127 else if (*pcbStructInfo < bytesNeeded)
2129 SetLastError(ERROR_MORE_DATA);
2130 *pcbStructInfo = bytesNeeded;
2131 ret = FALSE;
2133 else
2135 PCRYPT_OBJID_BLOB blob = pvStructInfo;
2137 *pcbStructInfo = bytesNeeded;
2138 blob->cbData = encodedLen;
2139 if (encodedLen)
2141 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2142 blob->pbData = (LPBYTE)pbEncoded;
2143 else
2145 assert(blob->pbData);
2146 memcpy(blob->pbData, pbEncoded, blob->cbData);
2149 else
2150 blob->pbData = NULL;
2152 if (pcbDecoded)
2153 *pcbDecoded = encodedLen;
2155 return ret;
2158 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2159 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2161 BOOL ret;
2162 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2163 offsetof(CTL_USAGE, cUsageIdentifier),
2164 offsetof(CTL_USAGE, rgpszUsageIdentifier),
2165 sizeof(CTL_USAGE),
2166 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2168 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2169 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2170 return ret;
2173 static BOOL CRYPT_AsnDecodeCTLEntryAttributes(const BYTE *pbEncoded,
2174 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2175 DWORD *pcbDecoded)
2177 struct AsnArrayDescriptor arrayDesc = { 0,
2178 offsetof(CTL_ENTRY, cAttribute), offsetof(CTL_ENTRY, rgAttribute),
2179 FINALMEMBERSIZE(CTL_ENTRY, cAttribute),
2180 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2181 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2182 BOOL ret;
2184 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2185 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2186 return ret;
2189 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2190 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2192 struct AsnDecodeSequenceItem items[] = {
2193 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2194 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2195 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2196 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2197 CRYPT_AsnDecodeCTLEntryAttributes,
2198 FINALMEMBERSIZE(CTL_ENTRY, cAttribute), FALSE, TRUE,
2199 offsetof(CTL_ENTRY, rgAttribute), 0 },
2201 BOOL ret = TRUE;
2202 CTL_ENTRY *entry = pvStructInfo;
2204 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
2205 *pcbStructInfo);
2207 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2208 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2209 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2210 return ret;
2213 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2214 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2216 BOOL ret;
2217 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2218 offsetof(CTL_INFO, cCTLEntry), offsetof(CTL_INFO, rgCTLEntry),
2219 FINALMEMBERSIZE(CTL_INFO, cExtension),
2220 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2221 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2223 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
2224 pvStructInfo, *pcbStructInfo, pcbDecoded);
2226 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2227 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2228 return ret;
2231 static BOOL CRYPT_AsnDecodeCTLExtensionsInternal(const BYTE *pbEncoded,
2232 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2233 DWORD *pcbDecoded)
2235 BOOL ret = TRUE;
2236 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2237 offsetof(CTL_INFO, cExtension), offsetof(CTL_INFO, rgExtension),
2238 FINALMEMBERSIZE(CTL_INFO, cExtension),
2239 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
2240 offsetof(CERT_EXTENSION, pszObjId) };
2242 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
2243 pvStructInfo, *pcbStructInfo, pcbDecoded);
2245 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2246 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2247 return ret;
2250 static BOOL CRYPT_AsnDecodeCTLExtensions(const BYTE *pbEncoded,
2251 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2252 DWORD *pcbDecoded)
2254 BOOL ret;
2255 DWORD dataLen;
2257 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2259 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2261 ret = CRYPT_AsnDecodeCTLExtensionsInternal(pbEncoded + 1 + lenBytes,
2262 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2263 if (ret && pcbDecoded)
2264 *pcbDecoded = 1 + lenBytes + dataLen;
2266 return ret;
2269 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2270 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2271 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2273 BOOL ret = FALSE;
2275 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2276 pDecodePara, pvStructInfo, *pcbStructInfo);
2278 __TRY
2280 struct AsnDecodeSequenceItem items[] = {
2281 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2282 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2283 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2284 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2285 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2286 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2287 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), TRUE,
2288 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2289 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2290 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2291 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2292 { 0, offsetof(CTL_INFO, ThisUpdate),
2293 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2294 0 },
2295 { 0, offsetof(CTL_INFO, NextUpdate),
2296 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2297 0 },
2298 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2299 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2300 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2301 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2302 CRYPT_AsnDecodeCTLEntries,
2303 MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension),
2304 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2305 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2306 CRYPT_AsnDecodeCTLExtensions, FINALMEMBERSIZE(CTL_INFO, cExtension),
2307 TRUE, TRUE, offsetof(CTL_INFO, rgExtension), 0 },
2310 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2311 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2312 pcbStructInfo, NULL, NULL);
2314 __EXCEPT_PAGE_FAULT
2316 SetLastError(STATUS_ACCESS_VIOLATION);
2318 __ENDTRY
2319 return ret;
2322 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2323 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2324 DWORD *pcbDecoded)
2326 BOOL ret;
2327 struct AsnDecodeSequenceItem items[] = {
2328 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2329 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2330 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2331 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2332 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2333 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2335 PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
2337 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2338 pvStructInfo, *pcbStructInfo);
2340 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2341 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2342 pcbDecoded, capability ? capability->pszObjId : NULL);
2343 TRACE("returning %d\n", ret);
2344 return ret;
2347 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2348 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2349 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2351 BOOL ret = FALSE;
2353 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2354 pDecodePara, pvStructInfo, *pcbStructInfo);
2356 __TRY
2358 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2359 offsetof(CRYPT_SMIME_CAPABILITIES, cCapability),
2360 offsetof(CRYPT_SMIME_CAPABILITIES, rgCapability),
2361 sizeof(CRYPT_SMIME_CAPABILITIES),
2362 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2363 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2364 CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
2366 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2367 capabilities->rgCapability = (CRYPT_SMIME_CAPABILITY *)(capabilities + 1);
2368 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2369 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2371 __EXCEPT_PAGE_FAULT
2373 SetLastError(STATUS_ACCESS_VIOLATION);
2375 __ENDTRY
2376 TRACE("returning %d\n", ret);
2377 return ret;
2380 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
2381 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2382 DWORD *pcbDecoded)
2384 BOOL ret = TRUE;
2385 DWORD dataLen;
2386 LPSTR *pStr = pvStructInfo;
2388 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2390 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2391 DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
2393 if (pbEncoded[0] != ASN_IA5STRING)
2395 SetLastError(CRYPT_E_ASN1_CORRUPT);
2396 ret = FALSE;
2398 else
2400 bytesNeeded += dataLen;
2401 if (pcbDecoded)
2402 *pcbDecoded = 1 + lenBytes + dataLen;
2403 if (!pvStructInfo)
2404 *pcbStructInfo = bytesNeeded;
2405 else if (*pcbStructInfo < bytesNeeded)
2407 *pcbStructInfo = bytesNeeded;
2408 SetLastError(ERROR_MORE_DATA);
2409 ret = FALSE;
2411 else
2413 *pcbStructInfo = bytesNeeded;
2414 if (dataLen)
2416 LPSTR str = *pStr;
2418 assert(str);
2419 memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
2420 str[dataLen] = 0;
2422 else
2423 *pStr = NULL;
2427 return ret;
2430 static BOOL CRYPT_AsnDecodeNoticeNumbers(const BYTE *pbEncoded,
2431 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2432 DWORD *pcbDecoded)
2434 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2435 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2436 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, rgNoticeNumbers),
2437 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2438 CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
2439 BOOL ret;
2441 TRACE("(%p, %ld, %08lx, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2442 pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
2444 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2445 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2446 TRACE("returning %d\n", ret);
2447 return ret;
2450 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
2451 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2452 DWORD *pcbDecoded)
2454 BOOL ret;
2455 struct AsnDecodeSequenceItem items[] = {
2456 { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2457 pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
2458 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
2459 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2460 cNoticeNumbers), CRYPT_AsnDecodeNoticeNumbers,
2461 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2462 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2463 rgNoticeNumbers), 0 },
2465 DWORD bytesNeeded = 0;
2467 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2468 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2470 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2471 pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
2472 NULL);
2473 if (ret)
2475 /* The caller is expecting a pointer to a
2476 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
2477 * CRYPT_AsnDecodeSequence is decoding a
2478 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. Increment the bytes
2479 * needed, and decode again if the requisite space is available.
2481 bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
2482 if (!pvStructInfo)
2483 *pcbStructInfo = bytesNeeded;
2484 else if (*pcbStructInfo < bytesNeeded)
2486 *pcbStructInfo = bytesNeeded;
2487 SetLastError(ERROR_MORE_DATA);
2488 ret = FALSE;
2490 else
2492 PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
2494 *pcbStructInfo = bytesNeeded;
2495 /* The pointer (pvStructInfo) passed in points to the first dynamic
2496 * pointer, so use it as the pointer to the
2497 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
2498 * appropriate offset for the first dynamic pointer within the
2499 * notice reference by pointing to the first memory location past
2500 * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
2502 noticeRef =
2503 *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
2504 noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
2505 sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
2506 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags,
2507 NULL, noticeRef, &bytesNeeded, pcbDecoded, noticeRef->pszOrganization);
2510 TRACE("returning %d\n", ret);
2511 return ret;
2514 static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
2515 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2516 DWORD *pcbDecoded)
2518 BOOL ret = TRUE;
2519 DWORD dataLen;
2521 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2523 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2524 DWORD bytesNeeded = sizeof(LPWSTR);
2526 switch (pbEncoded[0])
2528 case ASN_NUMERICSTRING:
2529 if (dataLen)
2530 bytesNeeded += (dataLen + 1) * 2;
2531 break;
2532 case ASN_PRINTABLESTRING:
2533 if (dataLen)
2534 bytesNeeded += (dataLen + 1) * 2;
2535 break;
2536 case ASN_IA5STRING:
2537 if (dataLen)
2538 bytesNeeded += (dataLen + 1) * 2;
2539 break;
2540 case ASN_T61STRING:
2541 if (dataLen)
2542 bytesNeeded += (dataLen + 1) * 2;
2543 break;
2544 case ASN_VIDEOTEXSTRING:
2545 if (dataLen)
2546 bytesNeeded += (dataLen + 1) * 2;
2547 break;
2548 case ASN_GRAPHICSTRING:
2549 if (dataLen)
2550 bytesNeeded += (dataLen + 1) * 2;
2551 break;
2552 case ASN_VISIBLESTRING:
2553 if (dataLen)
2554 bytesNeeded += (dataLen + 1) * 2;
2555 break;
2556 case ASN_GENERALSTRING:
2557 if (dataLen)
2558 bytesNeeded += (dataLen + 1) * 2;
2559 break;
2560 case ASN_UNIVERSALSTRING:
2561 if (dataLen)
2562 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
2563 break;
2564 case ASN_BMPSTRING:
2565 if (dataLen)
2566 bytesNeeded += dataLen + sizeof(WCHAR);
2567 break;
2568 case ASN_UTF8STRING:
2569 if (dataLen)
2570 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
2571 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
2572 break;
2573 default:
2574 SetLastError(CRYPT_E_ASN1_BADTAG);
2575 return FALSE;
2578 if (pcbDecoded)
2579 *pcbDecoded = 1 + lenBytes + dataLen;
2580 if (!pvStructInfo)
2581 *pcbStructInfo = bytesNeeded;
2582 else if (*pcbStructInfo < bytesNeeded)
2584 *pcbStructInfo = bytesNeeded;
2585 SetLastError(ERROR_MORE_DATA);
2586 ret = FALSE;
2588 else
2590 LPWSTR *pStr = pvStructInfo;
2592 *pcbStructInfo = bytesNeeded;
2593 if (dataLen)
2595 DWORD i;
2596 LPWSTR str = *pStr;
2598 assert(str);
2599 switch (pbEncoded[0])
2601 case ASN_NUMERICSTRING:
2602 case ASN_PRINTABLESTRING:
2603 case ASN_IA5STRING:
2604 case ASN_T61STRING:
2605 case ASN_VIDEOTEXSTRING:
2606 case ASN_GRAPHICSTRING:
2607 case ASN_VISIBLESTRING:
2608 case ASN_GENERALSTRING:
2609 for (i = 0; i < dataLen; i++)
2610 str[i] = pbEncoded[1 + lenBytes + i];
2611 str[i] = 0;
2612 break;
2613 case ASN_UNIVERSALSTRING:
2614 for (i = 0; i < dataLen / 4; i++)
2615 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2616 | pbEncoded[1 + lenBytes + 2 * i + 3];
2617 str[i] = 0;
2618 break;
2619 case ASN_BMPSTRING:
2620 for (i = 0; i < dataLen / 2; i++)
2621 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2622 pbEncoded[1 + lenBytes + 2 * i + 1];
2623 str[i] = 0;
2624 break;
2625 case ASN_UTF8STRING:
2627 int len = MultiByteToWideChar(CP_UTF8, 0,
2628 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2629 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
2630 str[len] = 0;
2631 break;
2635 else
2636 *pStr = NULL;
2639 return ret;
2642 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2643 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2644 DWORD *pcbStructInfo, DWORD *pcbDecoded)
2646 BOOL ret;
2647 struct AsnDecodeSequenceItem items[] = {
2648 { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2649 pNoticeReference), CRYPT_AsnDecodeNoticeReference,
2650 sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
2651 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
2652 { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
2653 CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
2654 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
2656 PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
2658 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2659 pvStructInfo, *pcbStructInfo);
2661 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2662 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2663 pcbDecoded, notice ? notice->pNoticeReference : NULL);
2664 TRACE("returning %d\n", ret);
2665 return ret;
2668 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
2669 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2670 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2671 void *pvStructInfo, DWORD *pcbStructInfo)
2673 BOOL ret = FALSE;
2675 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2676 pDecodePara, pvStructInfo, *pcbStructInfo);
2678 __TRY
2680 DWORD bytesNeeded = 0;
2682 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
2683 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2684 NULL);
2685 if (ret)
2687 if (!pvStructInfo)
2688 *pcbStructInfo = bytesNeeded;
2689 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2690 pvStructInfo, pcbStructInfo, bytesNeeded)))
2692 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
2694 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2695 pvStructInfo = *(BYTE **)pvStructInfo;
2696 notice = pvStructInfo;
2697 notice->pNoticeReference =
2698 (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
2699 ((BYTE *)pvStructInfo +
2700 sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
2701 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2702 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
2703 pvStructInfo, &bytesNeeded, NULL);
2704 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2705 CRYPT_FreeSpace(pDecodePara, notice);
2709 __EXCEPT_PAGE_FAULT
2711 SetLastError(STATUS_ACCESS_VIOLATION);
2713 __ENDTRY
2714 TRACE("returning %d\n", ret);
2715 return ret;
2718 static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded,
2719 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2720 DWORD *pcbDecoded)
2722 BOOL ret;
2723 struct AsnArrayDescriptor arrayDesc = { 0,
2724 offsetof(CRYPT_ATTRIBUTE, cValue), offsetof(CRYPT_ATTRIBUTE, rgValue),
2725 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue),
2726 CRYPT_AsnDecodeCopyBytes,
2727 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2729 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
2730 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
2732 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2733 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2734 return ret;
2737 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2738 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2739 DWORD *pcbDecoded)
2741 BOOL ret;
2742 struct AsnDecodeSequenceItem items[] = {
2743 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2744 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2745 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2746 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2747 CRYPT_AsnDecodePKCSAttributeValue,
2748 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE,
2749 TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2751 PCRYPT_ATTRIBUTE attr = pvStructInfo;
2753 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2754 pvStructInfo, *pcbStructInfo);
2756 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2757 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2758 pcbDecoded, attr ? attr->pszObjId : NULL);
2759 TRACE("returning %d\n", ret);
2760 return ret;
2763 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2764 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2765 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2767 BOOL ret = FALSE;
2769 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2770 pDecodePara, pvStructInfo, *pcbStructInfo);
2772 __TRY
2774 DWORD bytesNeeded = 0;
2776 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2777 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2778 if (ret)
2780 if (!pvStructInfo)
2781 *pcbStructInfo = bytesNeeded;
2782 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2783 pvStructInfo, pcbStructInfo, bytesNeeded)))
2785 PCRYPT_ATTRIBUTE attr;
2787 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2788 pvStructInfo = *(BYTE **)pvStructInfo;
2789 attr = pvStructInfo;
2790 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2791 sizeof(CRYPT_ATTRIBUTE));
2792 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2793 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2794 NULL);
2795 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2796 CRYPT_FreeSpace(pDecodePara, attr);
2800 __EXCEPT_PAGE_FAULT
2802 SetLastError(STATUS_ACCESS_VIOLATION);
2804 __ENDTRY
2805 TRACE("returning %d\n", ret);
2806 return ret;
2809 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2810 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2811 DWORD *pcbDecoded)
2813 struct AsnArrayDescriptor arrayDesc = { 0,
2814 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2815 sizeof(CRYPT_ATTRIBUTES),
2816 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2817 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2818 BOOL ret;
2820 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2821 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2822 return ret;
2825 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2826 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2827 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2829 BOOL ret = FALSE;
2831 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2832 pDecodePara, pvStructInfo, *pcbStructInfo);
2834 __TRY
2836 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
2837 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2838 sizeof(CRYPT_ATTRIBUTES),
2839 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE),
2840 TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2841 CRYPT_ATTRIBUTES *attrs = pvStructInfo;
2843 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2844 attrs->rgAttr = (CRYPT_ATTRIBUTE *)(attrs + 1);
2845 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2846 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2848 __EXCEPT_PAGE_FAULT
2850 SetLastError(STATUS_ACCESS_VIOLATION);
2852 __ENDTRY
2853 TRACE("returning %d\n", ret);
2854 return ret;
2857 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2858 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2860 CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
2861 BOOL ret = TRUE;
2862 struct AsnDecodeSequenceItem items[] = {
2863 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2864 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2865 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2866 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2867 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2868 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2871 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
2872 pvStructInfo, *pcbStructInfo, pcbDecoded);
2874 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2875 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2876 pcbDecoded, algo ? algo->pszObjId : NULL);
2877 if (ret && pvStructInfo)
2879 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2880 debugstr_a(algo->pszObjId));
2882 return ret;
2885 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2886 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2887 DWORD *pcbDecoded)
2889 BOOL ret = TRUE;
2890 struct AsnDecodeSequenceItem items[] = {
2891 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2892 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2893 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2894 Algorithm.pszObjId) },
2895 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2896 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2897 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2899 PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
2901 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2902 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2903 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2904 return ret;
2907 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2908 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2909 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2911 BOOL ret = TRUE;
2913 __TRY
2915 DWORD bytesNeeded = 0;
2917 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2918 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2920 if (!pvStructInfo)
2921 *pcbStructInfo = bytesNeeded;
2922 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2923 pvStructInfo, pcbStructInfo, bytesNeeded)))
2925 PCERT_PUBLIC_KEY_INFO info;
2927 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2928 pvStructInfo = *(BYTE **)pvStructInfo;
2929 info = pvStructInfo;
2930 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2931 sizeof(CERT_PUBLIC_KEY_INFO);
2932 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2933 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2934 &bytesNeeded, NULL);
2935 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2936 CRYPT_FreeSpace(pDecodePara, info);
2940 __EXCEPT_PAGE_FAULT
2942 SetLastError(STATUS_ACCESS_VIOLATION);
2943 ret = FALSE;
2945 __ENDTRY
2946 return ret;
2949 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2950 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2952 BOOL ret;
2954 if (cbEncoded < 3)
2956 SetLastError(CRYPT_E_ASN1_CORRUPT);
2957 return FALSE;
2959 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2961 SetLastError(CRYPT_E_ASN1_CORRUPT);
2962 return FALSE;
2964 if (pbEncoded[1] > 1)
2966 SetLastError(CRYPT_E_ASN1_CORRUPT);
2967 return FALSE;
2969 if (pcbDecoded)
2970 *pcbDecoded = 3;
2971 if (!pvStructInfo)
2973 *pcbStructInfo = sizeof(BOOL);
2974 ret = TRUE;
2976 else if (*pcbStructInfo < sizeof(BOOL))
2978 *pcbStructInfo = sizeof(BOOL);
2979 SetLastError(ERROR_MORE_DATA);
2980 ret = FALSE;
2982 else
2984 *pcbStructInfo = sizeof(BOOL);
2985 *(BOOL *)pvStructInfo = pbEncoded[2] != 0;
2986 ret = TRUE;
2988 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2989 return ret;
2992 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2993 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2995 PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
2996 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2997 BOOL ret;
2999 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3000 pvStructInfo, *pcbStructInfo);
3002 if (cbEncoded < 2)
3004 SetLastError(CRYPT_E_ASN1_CORRUPT);
3005 return FALSE;
3007 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3008 if (1 + lenBytes > cbEncoded)
3010 SetLastError(CRYPT_E_ASN1_CORRUPT);
3011 return FALSE;
3013 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3015 switch (pbEncoded[0] & ASN_TYPE_MASK)
3017 case 1: /* rfc822Name */
3018 case 2: /* dNSName */
3019 case 6: /* uniformResourceIdentifier */
3020 if (memchr(pbEncoded + 1 + lenBytes, 0, dataLen))
3022 SetLastError(CRYPT_E_ASN1_RULE);
3023 ret = FALSE;
3025 else
3026 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
3027 break;
3028 case 4: /* directoryName */
3029 case 7: /* iPAddress */
3030 bytesNeeded += dataLen;
3031 break;
3032 case 8: /* registeredID */
3033 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
3034 &dataLen, NULL);
3035 if (ret)
3037 /* FIXME: ugly, shouldn't need to know internals of OID decode
3038 * function to use it.
3040 bytesNeeded += dataLen - sizeof(LPSTR);
3042 break;
3043 case 0: /* otherName */
3044 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
3045 SetLastError(CRYPT_E_ASN1_BADTAG);
3046 ret = FALSE;
3047 break;
3048 case 3: /* x400Address, unimplemented */
3049 case 5: /* ediPartyName, unimplemented */
3050 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
3051 SetLastError(CRYPT_E_ASN1_BADTAG);
3052 ret = FALSE;
3053 break;
3054 default:
3055 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
3056 SetLastError(CRYPT_E_ASN1_CORRUPT);
3057 ret = FALSE;
3059 if (ret)
3061 if (pcbDecoded)
3062 *pcbDecoded = 1 + lenBytes + dataLen;
3063 if (!entry)
3064 *pcbStructInfo = bytesNeeded;
3065 else if (*pcbStructInfo < bytesNeeded)
3067 *pcbStructInfo = bytesNeeded;
3068 SetLastError(ERROR_MORE_DATA);
3069 ret = FALSE;
3071 else
3073 *pcbStructInfo = bytesNeeded;
3074 /* MS used values one greater than the asn1 ones.. sigh */
3075 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
3076 switch (pbEncoded[0] & ASN_TYPE_MASK)
3078 case 1: /* rfc822Name */
3079 case 2: /* dNSName */
3080 case 6: /* uniformResourceIdentifier */
3082 DWORD i;
3084 for (i = 0; i < dataLen; i++)
3085 entry->pwszURL[i] = (WCHAR)pbEncoded[1 + lenBytes + i];
3086 entry->pwszURL[i] = 0;
3087 TRACE("URL is %p (%s)\n", entry->pwszURL,
3088 debugstr_w(entry->pwszURL));
3089 break;
3091 case 4: /* directoryName */
3092 /* The data are memory-equivalent with the IPAddress case,
3093 * fall-through
3095 case 7: /* iPAddress */
3096 /* The next data pointer is in the pwszURL spot, that is,
3097 * the first 4 bytes. Need to move it to the next spot.
3099 entry->IPAddress.pbData = (LPBYTE)entry->pwszURL;
3100 entry->IPAddress.cbData = dataLen;
3101 memcpy(entry->IPAddress.pbData, pbEncoded + 1 + lenBytes,
3102 dataLen);
3103 break;
3104 case 8: /* registeredID */
3105 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
3106 &entry->pszRegisteredID, &dataLen, NULL);
3107 break;
3112 return ret;
3115 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
3116 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3117 DWORD *pcbDecoded)
3119 BOOL ret;
3120 struct AsnArrayDescriptor arrayDesc = { 0,
3121 offsetof(CERT_ALT_NAME_INFO, cAltEntry),
3122 offsetof(CERT_ALT_NAME_INFO, rgAltEntry),
3123 sizeof(CERT_ALT_NAME_INFO),
3124 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3125 offsetof(CERT_ALT_NAME_ENTRY, pwszURL) };
3127 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
3128 pvStructInfo, *pcbStructInfo, pcbDecoded);
3130 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3131 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3132 return ret;
3135 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
3136 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3137 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3139 BOOL ret;
3141 __TRY
3143 struct AsnDecodeSequenceItem items[] = {
3144 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
3145 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB),
3146 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
3147 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3148 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
3149 CRYPT_AsnDecodeOctets, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
3150 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
3151 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
3152 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3153 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3154 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
3157 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3158 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3159 pcbStructInfo, NULL, NULL);
3161 __EXCEPT_PAGE_FAULT
3163 SetLastError(STATUS_ACCESS_VIOLATION);
3164 ret = FALSE;
3166 __ENDTRY
3167 return ret;
3170 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
3171 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3172 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3174 BOOL ret;
3176 __TRY
3178 struct AsnDecodeSequenceItem items[] = {
3179 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
3180 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB),
3181 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
3182 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3183 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
3184 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
3185 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3186 AuthorityCertIssuer.rgAltEntry), 0 },
3187 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3188 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3189 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3190 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3191 AuthorityCertSerialNumber.pbData), 0 },
3194 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3195 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3196 pcbStructInfo, NULL, NULL);
3198 __EXCEPT_PAGE_FAULT
3200 SetLastError(STATUS_ACCESS_VIOLATION);
3201 ret = FALSE;
3203 __ENDTRY
3204 return ret;
3207 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
3208 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3209 DWORD *pcbDecoded)
3211 struct AsnDecodeSequenceItem items[] = {
3212 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
3213 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3214 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
3215 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
3216 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
3217 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.pwszURL), 0 },
3219 CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
3221 return CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3222 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3223 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
3226 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
3227 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3228 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3230 BOOL ret;
3232 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3233 pDecodePara, pvStructInfo, *pcbStructInfo);
3235 __TRY
3237 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3238 offsetof(CERT_AUTHORITY_INFO_ACCESS, cAccDescr),
3239 offsetof(CERT_AUTHORITY_INFO_ACCESS, rgAccDescr),
3240 sizeof(CERT_AUTHORITY_INFO_ACCESS),
3241 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
3242 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
3243 CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
3245 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3246 info->rgAccDescr = (CERT_ACCESS_DESCRIPTION *)(info + 1);
3247 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3248 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3250 __EXCEPT_PAGE_FAULT
3252 SetLastError(STATUS_ACCESS_VIOLATION);
3253 ret = FALSE;
3255 __ENDTRY
3256 return ret;
3259 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
3260 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3262 BOOL ret;
3263 DWORD dataLen;
3265 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
3266 pvStructInfo, *pcbStructInfo, pcbDecoded);
3268 /* The caller has already checked the tag, no need to check it again.
3269 * Check the outer length is valid:
3271 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
3273 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3274 DWORD innerLen;
3276 pbEncoded += 1 + lenBytes;
3277 cbEncoded -= 1 + lenBytes;
3278 if (dataLen == CMSG_INDEFINITE_LENGTH)
3279 cbEncoded -= 2; /* space for 0 TLV */
3280 /* Check the inner length is valid: */
3281 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
3283 DWORD decodedLen;
3285 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
3286 pvStructInfo, pcbStructInfo, &decodedLen);
3287 if (dataLen == CMSG_INDEFINITE_LENGTH)
3289 if (*(pbEncoded + decodedLen) != 0 ||
3290 *(pbEncoded + decodedLen + 1) != 0)
3292 TRACE("expected 0 TLV, got {%02x,%02x}\n",
3293 *(pbEncoded + decodedLen),
3294 *(pbEncoded + decodedLen + 1));
3295 SetLastError(CRYPT_E_ASN1_CORRUPT);
3296 ret = FALSE;
3298 else
3299 decodedLen += 2;
3301 if (ret && pcbDecoded)
3303 *pcbDecoded = 1 + lenBytes + decodedLen;
3304 TRACE("decoded %ld bytes\n", *pcbDecoded);
3308 return ret;
3311 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
3312 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3313 DWORD *pcbDecoded)
3315 CRYPT_CONTENT_INFO *info = pvStructInfo;
3316 struct AsnDecodeSequenceItem items[] = {
3317 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
3318 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3319 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
3320 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
3321 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
3322 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
3323 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
3325 BOOL ret;
3327 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
3328 pvStructInfo, *pcbStructInfo, pcbDecoded);
3330 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3331 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3332 pcbDecoded, info ? info->pszObjId : NULL);
3333 return ret;
3336 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
3337 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3338 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3340 BOOL ret = FALSE;
3342 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3343 pDecodePara, pvStructInfo, *pcbStructInfo);
3345 __TRY
3347 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
3348 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3349 if (ret && pvStructInfo)
3351 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3352 pcbStructInfo, *pcbStructInfo);
3353 if (ret)
3355 CRYPT_CONTENT_INFO *info;
3357 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3358 pvStructInfo = *(BYTE **)pvStructInfo;
3359 info = pvStructInfo;
3360 info->pszObjId = (LPSTR)((BYTE *)info +
3361 sizeof(CRYPT_CONTENT_INFO));
3362 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
3363 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3364 pcbStructInfo, NULL);
3365 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3366 CRYPT_FreeSpace(pDecodePara, info);
3370 __EXCEPT_PAGE_FAULT
3372 SetLastError(STATUS_ACCESS_VIOLATION);
3374 __ENDTRY
3375 return ret;
3378 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
3379 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3380 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
3382 BOOL ret;
3383 struct AsnDecodeSequenceItem items[] = {
3384 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
3385 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3386 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
3387 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3388 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
3389 0 },
3390 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
3391 CRYPT_AsnDecodePKCSContentInfoInternal,
3392 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
3393 ContentInfo.pszObjId), 0 },
3394 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
3395 CRYPT_AsnDecodeOctets, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
3396 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
3399 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3400 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
3401 NULL, NULL);
3402 return ret;
3405 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
3406 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3407 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3409 BOOL ret = TRUE;
3411 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3412 pDecodePara, pvStructInfo, *pcbStructInfo);
3414 __TRY
3416 DWORD bytesNeeded = 0;
3418 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3419 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3421 if (!pvStructInfo)
3422 *pcbStructInfo = bytesNeeded;
3423 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3424 pvStructInfo, pcbStructInfo, bytesNeeded)))
3426 CERT_ALT_NAME_INFO *name;
3428 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3429 pvStructInfo = *(BYTE **)pvStructInfo;
3430 name = pvStructInfo;
3431 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
3432 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
3433 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3434 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3435 &bytesNeeded, NULL);
3436 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3437 CRYPT_FreeSpace(pDecodePara, name);
3441 __EXCEPT_PAGE_FAULT
3443 SetLastError(STATUS_ACCESS_VIOLATION);
3444 ret = FALSE;
3446 __ENDTRY
3447 return ret;
3450 struct PATH_LEN_CONSTRAINT
3452 BOOL fPathLenConstraint;
3453 DWORD dwPathLenConstraint;
3456 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3457 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3458 DWORD *pcbDecoded)
3460 BOOL ret = TRUE;
3461 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3463 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
3464 pvStructInfo, *pcbStructInfo, pcbDecoded);
3466 if (!pvStructInfo)
3468 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3469 &size, pcbDecoded);
3470 *pcbStructInfo = bytesNeeded;
3472 else if (*pcbStructInfo < bytesNeeded)
3474 SetLastError(ERROR_MORE_DATA);
3475 *pcbStructInfo = bytesNeeded;
3476 ret = FALSE;
3478 else
3480 struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
3482 *pcbStructInfo = bytesNeeded;
3483 size = sizeof(constraint->dwPathLenConstraint);
3484 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3485 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3486 if (ret)
3487 constraint->fPathLenConstraint = TRUE;
3488 TRACE("got an int, dwPathLenConstraint is %ld\n",
3489 constraint->dwPathLenConstraint);
3491 TRACE("returning %d (%08lx)\n", ret, GetLastError());
3492 return ret;
3495 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3496 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3497 DWORD *pcbDecoded)
3499 BOOL ret;
3500 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3501 offsetof(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3502 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint),
3503 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3504 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3505 offsetof(CERT_NAME_BLOB, pbData) };
3507 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
3508 pvStructInfo, *pcbStructInfo, pcbDecoded);
3510 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3511 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3512 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
3513 return ret;
3516 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3517 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3518 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3520 BOOL ret;
3522 __TRY
3524 struct AsnDecodeSequenceItem items[] = {
3525 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3526 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3527 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3528 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3529 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3530 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3531 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3532 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3533 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3534 TRUE, TRUE,
3535 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3538 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3539 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3540 pcbStructInfo, NULL, NULL);
3542 __EXCEPT_PAGE_FAULT
3544 SetLastError(STATUS_ACCESS_VIOLATION);
3545 ret = FALSE;
3547 __ENDTRY
3548 return ret;
3551 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3552 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3553 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3555 BOOL ret;
3557 __TRY
3559 struct AsnDecodeSequenceItem items[] = {
3560 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3561 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3562 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3563 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3564 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3567 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3568 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3569 pcbStructInfo, NULL, NULL);
3571 __EXCEPT_PAGE_FAULT
3573 SetLastError(STATUS_ACCESS_VIOLATION);
3574 ret = FALSE;
3576 __ENDTRY
3577 return ret;
3580 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
3581 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3582 DWORD *pcbDecoded)
3584 struct AsnDecodeSequenceItem items[] = {
3585 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
3586 pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3587 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
3588 0 },
3589 { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
3590 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3591 offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
3593 BOOL ret;
3594 CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
3596 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3597 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3599 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3600 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3601 pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
3602 return ret;
3605 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
3606 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3607 DWORD *pcbDecoded)
3609 BOOL ret;
3610 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3611 offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3612 offsetof(CERT_POLICY_INFO, rgPolicyQualifier),
3613 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier),
3614 CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
3615 offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
3617 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3618 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3620 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3621 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3622 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
3623 return ret;
3626 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
3627 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3629 struct AsnDecodeSequenceItem items[] = {
3630 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
3631 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3632 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
3633 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3634 CRYPT_AsnDecodePolicyQualifiers,
3635 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier), TRUE,
3636 TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
3638 CERT_POLICY_INFO *info = pvStructInfo;
3639 BOOL ret;
3641 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3642 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3644 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3645 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3646 pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
3647 return ret;
3650 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
3651 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3652 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3654 BOOL ret = FALSE;
3656 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3657 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3659 __TRY
3661 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3662 offsetof(CERT_POLICIES_INFO, cPolicyInfo),
3663 offsetof(CERT_POLICIES_INFO, rgPolicyInfo),
3664 sizeof(CERT_POLICIES_INFO),
3665 CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
3666 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
3667 CERT_POLICIES_INFO *info = pvStructInfo;
3669 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3670 info->rgPolicyInfo = (CERT_POLICY_INFO *)(info + 1);
3672 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3673 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3675 __EXCEPT_PAGE_FAULT
3677 SetLastError(STATUS_ACCESS_VIOLATION);
3679 __ENDTRY
3680 return ret;
3683 static BOOL CRYPT_AsnDecodeCertPolicyMapping(const BYTE *pbEncoded,
3684 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3685 DWORD *pcbDecoded)
3687 struct AsnDecodeSequenceItem items[] = {
3688 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
3689 pszIssuerDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3690 FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy), 0 },
3691 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
3692 pszSubjectDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3693 FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszSubjectDomainPolicy), 0 },
3695 CERT_POLICY_MAPPING *mapping = pvStructInfo;
3696 BOOL ret;
3698 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3699 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3701 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3702 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3703 pcbDecoded, mapping ? mapping->pszIssuerDomainPolicy : NULL);
3704 return ret;
3707 static BOOL WINAPI CRYPT_AsnDecodeCertPolicyMappings(DWORD dwCertEncodingType,
3708 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3709 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3711 BOOL ret = FALSE;
3713 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3714 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3716 __TRY
3718 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3719 offsetof(CERT_POLICY_MAPPINGS_INFO, cPolicyMapping),
3720 offsetof(CERT_POLICY_MAPPINGS_INFO, rgPolicyMapping),
3721 sizeof(CERT_POLICY_MAPPING),
3722 CRYPT_AsnDecodeCertPolicyMapping, sizeof(CERT_POLICY_MAPPING), TRUE,
3723 offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy) };
3724 CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
3726 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3727 info->rgPolicyMapping = (CERT_POLICY_MAPPING *)(info + 1);
3728 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3729 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3731 __EXCEPT_PAGE_FAULT
3733 SetLastError(STATUS_ACCESS_VIOLATION);
3735 __ENDTRY
3736 return ret;
3739 static BOOL CRYPT_AsnDecodeRequireExplicit(const BYTE *pbEncoded,
3740 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3741 DWORD *pcbDecoded)
3743 BOOL ret;
3744 DWORD skip, size = sizeof(skip);
3746 if (!cbEncoded)
3748 SetLastError(CRYPT_E_ASN1_EOD);
3749 return FALSE;
3751 if (pbEncoded[0] != (ASN_CONTEXT | 0))
3753 SetLastError(CRYPT_E_ASN1_BADTAG);
3754 return FALSE;
3756 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3757 &skip, &size, pcbDecoded)))
3759 DWORD bytesNeeded = MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
3760 fRequireExplicitPolicy, fInhibitPolicyMapping);
3762 if (!pvStructInfo)
3763 *pcbStructInfo = bytesNeeded;
3764 else if (*pcbStructInfo < bytesNeeded)
3766 *pcbStructInfo = bytesNeeded;
3767 SetLastError(ERROR_MORE_DATA);
3768 ret = FALSE;
3770 else
3772 CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo,
3773 CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy);
3775 *pcbStructInfo = bytesNeeded;
3776 /* The BOOL is implicit: if the integer is present, then it's
3777 * TRUE.
3779 info->fRequireExplicitPolicy = TRUE;
3780 info->dwRequireExplicitPolicySkipCerts = skip;
3783 return ret;
3786 static BOOL CRYPT_AsnDecodeInhibitMapping(const BYTE *pbEncoded,
3787 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3788 DWORD *pcbDecoded)
3790 BOOL ret;
3791 DWORD skip, size = sizeof(skip);
3793 if (!cbEncoded)
3795 SetLastError(CRYPT_E_ASN1_EOD);
3796 return FALSE;
3798 if (pbEncoded[0] != (ASN_CONTEXT | 1))
3800 SetLastError(CRYPT_E_ASN1_BADTAG);
3801 return FALSE;
3803 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3804 &skip, &size, pcbDecoded)))
3806 DWORD bytesNeeded = FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
3807 fInhibitPolicyMapping);
3809 if (!pvStructInfo)
3810 *pcbStructInfo = bytesNeeded;
3811 else if (*pcbStructInfo < bytesNeeded)
3813 *pcbStructInfo = bytesNeeded;
3814 SetLastError(ERROR_MORE_DATA);
3815 ret = FALSE;
3817 else
3819 CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo,
3820 CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping);
3822 *pcbStructInfo = bytesNeeded;
3823 /* The BOOL is implicit: if the integer is present, then it's
3824 * TRUE.
3826 info->fInhibitPolicyMapping = TRUE;
3827 info->dwInhibitPolicyMappingSkipCerts = skip;
3830 return ret;
3833 static BOOL WINAPI CRYPT_AsnDecodeCertPolicyConstraints(
3834 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3835 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3836 void *pvStructInfo, DWORD *pcbStructInfo)
3838 BOOL ret = FALSE;
3840 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3841 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3843 __TRY
3845 struct AsnDecodeSequenceItem items[] = {
3846 { ASN_CONTEXT | 0,
3847 offsetof(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy),
3848 CRYPT_AsnDecodeRequireExplicit,
3849 MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy,
3850 fInhibitPolicyMapping), TRUE, FALSE, 0, 0 },
3851 { ASN_CONTEXT | 1,
3852 offsetof(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
3853 CRYPT_AsnDecodeInhibitMapping,
3854 FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
3855 TRUE, FALSE, 0, 0 },
3858 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3859 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3860 pcbStructInfo, NULL, NULL);
3862 __EXCEPT_PAGE_FAULT
3864 SetLastError(STATUS_ACCESS_VIOLATION);
3866 __ENDTRY
3867 return ret;
3870 #define RSA1_MAGIC 0x31415352
3872 struct DECODED_RSA_PUB_KEY
3874 CRYPT_INTEGER_BLOB pubexp;
3875 CRYPT_INTEGER_BLOB modulus;
3878 /* Helper function to decode an ASN.1 DER encoded RSA public key, writing the decoded
3879 * key into 'decodedKey', and the length into 'size'. The memory
3880 * for 'decodedKey' is allocated with 'CRYPT_DECODE_ALLOC_FLAG'
3882 static BOOL CRYPT_raw_decode_rsa_pub_key(struct DECODED_RSA_PUB_KEY **decodedKey,
3883 DWORD *size, const BYTE *pbEncoded, DWORD cbEncoded)
3885 BOOL ret;
3887 struct AsnDecodeSequenceItem items[] = {
3888 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3889 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3890 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3891 0 },
3892 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3893 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3894 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, pubexp.pbData),
3895 0 },
3898 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3899 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, decodedKey,
3900 size, NULL, NULL);
3902 if (ret && (*decodedKey)->pubexp.cbData > sizeof(DWORD))
3904 WARN("Unexpected exponent length %lu.\n", (*decodedKey)->pubexp.cbData);
3905 LocalFree(*decodedKey);
3906 SetLastError(CRYPT_E_ASN1_LARGE);
3907 ret = FALSE;
3910 return ret;
3913 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey_Bcrypt(DWORD dwCertEncodingType,
3914 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3915 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3917 BOOL ret;
3919 __TRY
3921 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3922 DWORD size = 0;
3924 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3925 pvStructInfo, *pcbStructInfo);
3927 ret = CRYPT_raw_decode_rsa_pub_key(&decodedKey, &size, pbEncoded, cbEncoded);
3928 if (ret)
3930 /* Header, exponent, and modulus */
3931 DWORD bytesNeeded = sizeof(BCRYPT_RSAKEY_BLOB) + decodedKey->pubexp.cbData +
3932 decodedKey->modulus.cbData;
3934 if (!pvStructInfo)
3936 *pcbStructInfo = bytesNeeded;
3937 ret = TRUE;
3939 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3940 pvStructInfo, pcbStructInfo, bytesNeeded)))
3942 BCRYPT_RSAKEY_BLOB *hdr;
3944 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3945 pvStructInfo = *(BYTE **)pvStructInfo;
3947 hdr = pvStructInfo;
3948 hdr->Magic = BCRYPT_RSAPUBLIC_MAGIC;
3949 hdr->BitLength = decodedKey->modulus.cbData * 8;
3950 hdr->cbPublicExp = decodedKey->pubexp.cbData;
3951 hdr->cbModulus = decodedKey->modulus.cbData;
3952 hdr->cbPrime1 = 0;
3953 hdr->cbPrime2 = 0;
3954 /* CNG_RSA_PUBLIC_KEY_BLOB always stores the exponent and modulus
3955 * in big-endian format, so we need to convert from little-endian
3957 CRYPT_CopyReversed((BYTE *)pvStructInfo + sizeof(BCRYPT_RSAKEY_BLOB),
3958 decodedKey->pubexp.pbData, hdr->cbPublicExp);
3959 CRYPT_CopyReversed((BYTE *)pvStructInfo + sizeof(BCRYPT_RSAKEY_BLOB) +
3960 hdr->cbPublicExp, decodedKey->modulus.pbData,
3961 decodedKey->modulus.cbData);
3963 LocalFree(decodedKey);
3966 __EXCEPT_PAGE_FAULT
3968 SetLastError(STATUS_ACCESS_VIOLATION);
3969 ret = FALSE;
3971 __ENDTRY
3972 return ret;
3976 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3977 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3978 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3980 BOOL ret;
3982 __TRY
3984 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3985 DWORD size = 0;
3986 ret = CRYPT_raw_decode_rsa_pub_key(&decodedKey, &size, pbEncoded, cbEncoded);
3987 if (ret)
3989 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3990 decodedKey->modulus.cbData;
3992 if (!pvStructInfo)
3994 *pcbStructInfo = bytesNeeded;
3996 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3997 pvStructInfo, pcbStructInfo, bytesNeeded)))
3999 BLOBHEADER *hdr;
4000 RSAPUBKEY *rsaPubKey;
4001 unsigned int i;
4003 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4004 pvStructInfo = *(BYTE **)pvStructInfo;
4005 hdr = pvStructInfo;
4006 hdr->bType = PUBLICKEYBLOB;
4007 hdr->bVersion = CUR_BLOB_VERSION;
4008 hdr->reserved = 0;
4009 hdr->aiKeyAlg = CALG_RSA_KEYX;
4010 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
4011 sizeof(BLOBHEADER));
4012 rsaPubKey->magic = RSA1_MAGIC;
4013 rsaPubKey->pubexp = 0;
4014 assert(decodedKey->pubexp.cbData <= sizeof(rsaPubKey->pubexp));
4015 for (i = 0; i < decodedKey->pubexp.cbData; ++i)
4016 rsaPubKey->pubexp |= decodedKey->pubexp.pbData[i] << (i * 8);
4018 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
4019 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
4020 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
4021 decodedKey->modulus.cbData);
4023 LocalFree(decodedKey);
4026 __EXCEPT_PAGE_FAULT
4028 SetLastError(STATUS_ACCESS_VIOLATION);
4029 ret = FALSE;
4031 __ENDTRY
4032 return ret;
4035 #define RSA2_MAGIC 0x32415352
4037 struct DECODED_RSA_PRIV_KEY
4039 DWORD version;
4040 DWORD pubexp;
4041 CRYPT_INTEGER_BLOB modulus;
4042 CRYPT_INTEGER_BLOB privexp;
4043 CRYPT_INTEGER_BLOB prime1;
4044 CRYPT_INTEGER_BLOB prime2;
4045 CRYPT_INTEGER_BLOB exponent1;
4046 CRYPT_INTEGER_BLOB exponent2;
4047 CRYPT_INTEGER_BLOB coefficient;
4050 static BOOL WINAPI CRYPT_AsnDecodeRsaPrivKey(DWORD dwCertEncodingType,
4051 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4052 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4054 BOOL ret;
4055 DWORD halflen;
4057 __TRY
4059 struct AsnDecodeSequenceItem items[] = {
4060 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, version),
4061 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4062 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, modulus),
4063 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4064 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, modulus.pbData),
4065 0 },
4066 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, pubexp),
4067 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4068 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, privexp),
4069 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4070 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, privexp.pbData),
4071 0 },
4072 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime1),
4073 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4074 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime1.pbData),
4075 0 },
4076 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime2),
4077 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4078 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime2.pbData),
4079 0 },
4080 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1),
4081 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4082 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1.pbData),
4083 0 },
4084 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2),
4085 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4086 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2.pbData),
4087 0 },
4088 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient),
4089 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4090 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient.pbData),
4091 0 },
4093 struct DECODED_RSA_PRIV_KEY *decodedKey = NULL;
4094 DWORD size = 0;
4096 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
4097 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
4098 &size, NULL, NULL);
4099 if (ret)
4101 halflen = decodedKey->prime1.cbData;
4102 if (halflen < decodedKey->prime2.cbData)
4103 halflen = decodedKey->prime2.cbData;
4104 if (halflen < decodedKey->exponent1.cbData)
4105 halflen = decodedKey->exponent1.cbData;
4106 if (halflen < decodedKey->exponent2.cbData)
4107 halflen = decodedKey->exponent2.cbData;
4108 if (halflen < decodedKey->coefficient.cbData)
4109 halflen = decodedKey->coefficient.cbData;
4110 if (halflen * 2 < decodedKey->modulus.cbData)
4111 halflen = decodedKey->modulus.cbData / 2 + decodedKey->modulus.cbData % 2;
4112 if (halflen * 2 < decodedKey->privexp.cbData)
4113 halflen = decodedKey->privexp.cbData / 2 + decodedKey->privexp.cbData % 2;
4115 if (ret)
4117 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
4118 (halflen * 9);
4120 if (!pvStructInfo)
4122 *pcbStructInfo = bytesNeeded;
4123 ret = TRUE;
4125 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4126 pvStructInfo, pcbStructInfo, bytesNeeded)))
4128 BLOBHEADER *hdr;
4129 RSAPUBKEY *rsaPubKey;
4130 BYTE *vardata;
4132 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4133 pvStructInfo = *(BYTE **)pvStructInfo;
4135 hdr = pvStructInfo;
4136 hdr->bType = PRIVATEKEYBLOB;
4137 hdr->bVersion = CUR_BLOB_VERSION;
4138 hdr->reserved = 0;
4139 hdr->aiKeyAlg = CALG_RSA_KEYX;
4141 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
4142 sizeof(BLOBHEADER));
4143 rsaPubKey->magic = RSA2_MAGIC;
4144 rsaPubKey->pubexp = decodedKey->pubexp;
4145 rsaPubKey->bitlen = halflen * 16;
4147 vardata = (BYTE*)(rsaPubKey + 1);
4148 memset(vardata, 0, halflen * 9);
4149 memcpy(vardata,
4150 decodedKey->modulus.pbData, decodedKey->modulus.cbData);
4151 memcpy(vardata + halflen * 2,
4152 decodedKey->prime1.pbData, decodedKey->prime1.cbData);
4153 memcpy(vardata + halflen * 3,
4154 decodedKey->prime2.pbData, decodedKey->prime2.cbData);
4155 memcpy(vardata + halflen * 4,
4156 decodedKey->exponent1.pbData, decodedKey->exponent1.cbData);
4157 memcpy(vardata + halflen * 5,
4158 decodedKey->exponent2.pbData, decodedKey->exponent2.cbData);
4159 memcpy(vardata + halflen * 6,
4160 decodedKey->coefficient.pbData, decodedKey->coefficient.cbData);
4161 memcpy(vardata + halflen * 7,
4162 decodedKey->privexp.pbData, decodedKey->privexp.cbData);
4166 LocalFree(decodedKey);
4169 __EXCEPT_PAGE_FAULT
4171 SetLastError(STATUS_ACCESS_VIOLATION);
4172 ret = FALSE;
4174 __ENDTRY
4175 return ret;
4178 static BOOL CRYPT_AsnDecodeOctets(const BYTE *pbEncoded,
4179 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4180 DWORD *pcbDecoded)
4182 BOOL ret;
4183 DWORD bytesNeeded, dataLen;
4185 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
4186 pvStructInfo, *pcbStructInfo, pcbDecoded);
4188 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4190 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4192 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4193 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
4194 else
4195 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
4196 if (pcbDecoded)
4197 *pcbDecoded = 1 + lenBytes + dataLen;
4198 if (!pvStructInfo)
4199 *pcbStructInfo = bytesNeeded;
4200 else if (*pcbStructInfo < bytesNeeded)
4202 SetLastError(ERROR_MORE_DATA);
4203 *pcbStructInfo = bytesNeeded;
4204 ret = FALSE;
4206 else
4208 CRYPT_DATA_BLOB *blob;
4210 *pcbStructInfo = bytesNeeded;
4211 blob = pvStructInfo;
4212 blob->cbData = dataLen;
4213 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4214 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
4215 else
4217 assert(blob->pbData);
4218 if (blob->cbData)
4219 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
4220 blob->cbData);
4224 return ret;
4227 static BOOL CRYPT_AsnDecodeOctetStringInternal(const BYTE *encoded, DWORD encoded_size,
4228 DWORD flags, void *buf, DWORD *buf_size, DWORD *ret_decoded)
4230 DWORD decoded = 0, indefinite_len_depth = 0, len_size, len, bytes_needed;
4231 CRYPT_DATA_BLOB *blob;
4232 const BYTE *string;
4234 while (encoded[0] == (ASN_CONSTRUCTOR | ASN_OCTETSTRING))
4236 if (!CRYPT_GetLengthIndefinite(encoded, encoded_size, &len))
4237 return FALSE;
4239 len_size = GET_LEN_BYTES(encoded[1]);
4240 encoded += 1 + len_size;
4241 encoded_size -= 1 + len_size;
4242 decoded += 1 + len_size;
4244 if (len == CMSG_INDEFINITE_LENGTH)
4246 indefinite_len_depth++;
4247 if (encoded_size < 2)
4249 SetLastError(CRYPT_E_ASN1_EOD);
4250 return FALSE;
4252 encoded_size -= 2;
4253 decoded += 2;
4257 if (encoded[0] != ASN_OCTETSTRING)
4259 WARN("Unexpected tag %02x\n", encoded[0]);
4260 SetLastError(CRYPT_E_ASN1_BADTAG);
4261 return FALSE;
4264 if (!CRYPT_GetLen(encoded, encoded_size, &len))
4265 return FALSE;
4266 len_size = GET_LEN_BYTES(encoded[1]);
4267 decoded += 1 + len_size + len;
4268 encoded_size -= 1 + len_size;
4270 if (len > encoded_size)
4272 SetLastError(CRYPT_E_ASN1_EOD);
4273 return FALSE;
4275 if (ret_decoded)
4276 *ret_decoded = decoded;
4278 encoded += 1 + len_size;
4279 string = encoded;
4280 encoded += len;
4282 while (indefinite_len_depth--)
4284 if (encoded[0] || encoded[1])
4286 TRACE("expected 0 TLV, got %02x %02x\n", encoded[0], encoded[1]);
4287 SetLastError(CRYPT_E_ASN1_CORRUPT);
4288 return FALSE;
4292 bytes_needed = sizeof(*blob);
4293 if (!(flags & CRYPT_DECODE_NOCOPY_FLAG)) bytes_needed += len;
4294 if (!buf)
4296 *buf_size = bytes_needed;
4297 return TRUE;
4299 if (*buf_size < bytes_needed)
4301 SetLastError(ERROR_MORE_DATA);
4302 *buf_size = bytes_needed;
4303 return FALSE;
4306 *buf_size = bytes_needed;
4307 blob = buf;
4308 blob->cbData = len;
4309 if (flags & CRYPT_DECODE_NOCOPY_FLAG)
4310 blob->pbData = (BYTE*)string;
4311 else if (blob->cbData)
4312 memcpy(blob->pbData, string, blob->cbData);
4314 if (ret_decoded)
4315 *ret_decoded = decoded;
4316 return TRUE;
4319 static BOOL WINAPI CRYPT_AsnDecodeOctetString(DWORD dwCertEncodingType,
4320 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4321 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4323 BOOL ret;
4325 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
4326 pDecodePara, pvStructInfo, *pcbStructInfo);
4328 if (!cbEncoded)
4330 SetLastError(CRYPT_E_ASN1_CORRUPT);
4331 return FALSE;
4334 __TRY
4336 DWORD bytesNeeded = 0;
4338 if ((ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded,
4339 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4341 if (!pvStructInfo)
4342 *pcbStructInfo = bytesNeeded;
4343 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4344 pvStructInfo, pcbStructInfo, bytesNeeded)))
4346 CRYPT_DATA_BLOB *blob;
4348 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4349 pvStructInfo = *(BYTE **)pvStructInfo;
4350 blob = pvStructInfo;
4351 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
4352 ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded,
4353 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4354 &bytesNeeded, NULL);
4355 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4356 CRYPT_FreeSpace(pDecodePara, blob);
4360 __EXCEPT_PAGE_FAULT
4362 SetLastError(STATUS_ACCESS_VIOLATION);
4363 ret = FALSE;
4365 __ENDTRY
4366 return ret;
4369 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4370 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4372 BOOL ret;
4373 DWORD bytesNeeded, dataLen;
4374 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4376 TRACE("(%p, %ld, 0x%08lx, %p, %ld, %p)\n", pbEncoded, cbEncoded, dwFlags,
4377 pvStructInfo, *pcbStructInfo, pcbDecoded);
4379 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4381 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4382 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
4383 else
4384 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
4385 if (pcbDecoded)
4386 *pcbDecoded = 1 + lenBytes + dataLen;
4387 if (!pvStructInfo)
4388 *pcbStructInfo = bytesNeeded;
4389 else if (*pcbStructInfo < bytesNeeded)
4391 *pcbStructInfo = bytesNeeded;
4392 SetLastError(ERROR_MORE_DATA);
4393 ret = FALSE;
4395 else
4397 CRYPT_BIT_BLOB *blob;
4399 *pcbStructInfo = bytesNeeded;
4400 blob = pvStructInfo;
4401 blob->cbData = dataLen - 1;
4402 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
4403 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4405 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
4407 else
4409 assert(blob->pbData);
4410 if (blob->cbData)
4412 BYTE mask = 0xff << blob->cUnusedBits;
4414 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
4415 blob->cbData);
4416 blob->pbData[blob->cbData - 1] &= mask;
4421 return ret;
4424 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
4425 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4426 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4428 BOOL ret;
4430 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
4431 pDecodePara, pvStructInfo, pcbStructInfo);
4433 __TRY
4435 DWORD bytesNeeded = 0;
4437 if (!cbEncoded)
4439 SetLastError(CRYPT_E_ASN1_CORRUPT);
4440 ret = FALSE;
4442 else if (pbEncoded[0] != ASN_BITSTRING)
4444 SetLastError(CRYPT_E_ASN1_BADTAG);
4445 ret = FALSE;
4447 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4448 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4450 if (!pvStructInfo)
4451 *pcbStructInfo = bytesNeeded;
4452 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4453 pvStructInfo, pcbStructInfo, bytesNeeded)))
4455 CRYPT_BIT_BLOB *blob;
4457 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4458 pvStructInfo = *(BYTE **)pvStructInfo;
4459 blob = pvStructInfo;
4460 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
4461 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4462 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4463 &bytesNeeded, NULL);
4464 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4465 CRYPT_FreeSpace(pDecodePara, blob);
4469 __EXCEPT_PAGE_FAULT
4471 SetLastError(STATUS_ACCESS_VIOLATION);
4472 ret = FALSE;
4474 __ENDTRY
4475 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4476 return ret;
4479 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
4480 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4481 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4483 BOOL ret;
4484 DWORD dataLen;
4486 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4488 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4490 if (pcbDecoded)
4491 *pcbDecoded = 1 + lenBytes + dataLen;
4492 if (dataLen > sizeof(int))
4494 SetLastError(CRYPT_E_ASN1_LARGE);
4495 ret = FALSE;
4497 else if (!pvStructInfo)
4498 *pcbStructInfo = sizeof(int);
4499 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
4501 int val, i;
4503 if (dataLen && pbEncoded[1 + lenBytes] & 0x80)
4505 /* initialize to a negative value to sign-extend */
4506 val = -1;
4508 else
4509 val = 0;
4510 for (i = 0; i < dataLen; i++)
4512 val <<= 8;
4513 val |= pbEncoded[1 + lenBytes + i];
4515 memcpy(pvStructInfo, &val, sizeof(int));
4518 return ret;
4521 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
4522 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4523 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4525 BOOL ret;
4527 __TRY
4529 DWORD bytesNeeded = 0;
4531 if (!cbEncoded)
4533 SetLastError(CRYPT_E_ASN1_EOD);
4534 ret = FALSE;
4536 else if (pbEncoded[0] != ASN_INTEGER)
4538 SetLastError(CRYPT_E_ASN1_BADTAG);
4539 ret = FALSE;
4541 else
4542 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4543 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4544 if (ret)
4546 if (!pvStructInfo)
4547 *pcbStructInfo = bytesNeeded;
4548 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4549 pvStructInfo, pcbStructInfo, bytesNeeded)))
4551 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4552 pvStructInfo = *(BYTE **)pvStructInfo;
4553 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4554 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4555 &bytesNeeded, NULL);
4556 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4557 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
4561 __EXCEPT_PAGE_FAULT
4563 SetLastError(STATUS_ACCESS_VIOLATION);
4564 ret = FALSE;
4566 __ENDTRY
4567 return ret;
4570 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
4571 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4572 DWORD *pcbDecoded)
4574 BOOL ret;
4575 DWORD bytesNeeded, dataLen;
4577 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4579 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4581 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4582 if (pcbDecoded)
4583 *pcbDecoded = 1 + lenBytes + dataLen;
4584 if (!pvStructInfo)
4585 *pcbStructInfo = bytesNeeded;
4586 else if (*pcbStructInfo < bytesNeeded)
4588 *pcbStructInfo = bytesNeeded;
4589 SetLastError(ERROR_MORE_DATA);
4590 ret = FALSE;
4592 else
4594 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4596 *pcbStructInfo = bytesNeeded;
4597 blob->cbData = dataLen;
4598 assert(blob->pbData);
4599 if (blob->cbData)
4601 DWORD i;
4603 for (i = 0; i < blob->cbData; i++)
4605 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4606 dataLen - i - 1);
4611 return ret;
4614 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4615 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4616 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4618 BOOL ret;
4620 __TRY
4622 DWORD bytesNeeded = 0;
4624 if (pbEncoded[0] != ASN_INTEGER)
4626 SetLastError(CRYPT_E_ASN1_BADTAG);
4627 ret = FALSE;
4629 else
4630 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4631 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4632 if (ret)
4634 if (!pvStructInfo)
4635 *pcbStructInfo = bytesNeeded;
4636 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4637 pvStructInfo, pcbStructInfo, bytesNeeded)))
4639 CRYPT_INTEGER_BLOB *blob;
4641 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4642 pvStructInfo = *(BYTE **)pvStructInfo;
4643 blob = pvStructInfo;
4644 blob->pbData = (BYTE *)pvStructInfo +
4645 sizeof(CRYPT_INTEGER_BLOB);
4646 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4647 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4648 &bytesNeeded, NULL);
4649 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4650 CRYPT_FreeSpace(pDecodePara, blob);
4654 __EXCEPT_PAGE_FAULT
4656 SetLastError(STATUS_ACCESS_VIOLATION);
4657 ret = FALSE;
4659 __ENDTRY
4660 return ret;
4663 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
4664 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4665 DWORD *pcbDecoded)
4667 BOOL ret;
4669 if (pbEncoded[0] == ASN_INTEGER)
4671 DWORD bytesNeeded, dataLen;
4673 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4675 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4677 if (pcbDecoded)
4678 *pcbDecoded = 1 + lenBytes + dataLen;
4679 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4680 if (!pvStructInfo)
4681 *pcbStructInfo = bytesNeeded;
4682 else if (*pcbStructInfo < bytesNeeded)
4684 *pcbStructInfo = bytesNeeded;
4685 SetLastError(ERROR_MORE_DATA);
4686 ret = FALSE;
4688 else
4690 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4692 *pcbStructInfo = bytesNeeded;
4693 blob->cbData = dataLen;
4694 assert(blob->pbData);
4695 /* remove leading zero byte if it exists */
4696 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4698 blob->cbData--;
4699 blob->pbData++;
4701 if (blob->cbData)
4703 DWORD i;
4705 for (i = 0; i < blob->cbData; i++)
4707 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4708 dataLen - i - 1);
4714 else
4716 SetLastError(CRYPT_E_ASN1_BADTAG);
4717 ret = FALSE;
4719 return ret;
4722 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4723 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4724 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4726 BOOL ret;
4728 __TRY
4730 DWORD bytesNeeded = 0;
4732 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4733 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4735 if (!pvStructInfo)
4736 *pcbStructInfo = bytesNeeded;
4737 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4738 pvStructInfo, pcbStructInfo, bytesNeeded)))
4740 CRYPT_INTEGER_BLOB *blob;
4742 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4743 pvStructInfo = *(BYTE **)pvStructInfo;
4744 blob = pvStructInfo;
4745 blob->pbData = (BYTE *)pvStructInfo +
4746 sizeof(CRYPT_INTEGER_BLOB);
4747 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4748 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4749 &bytesNeeded, NULL);
4750 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4751 CRYPT_FreeSpace(pDecodePara, blob);
4755 __EXCEPT_PAGE_FAULT
4757 SetLastError(STATUS_ACCESS_VIOLATION);
4758 ret = FALSE;
4760 __ENDTRY
4761 return ret;
4764 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4765 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4766 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4768 BOOL ret;
4770 if (!pvStructInfo)
4772 *pcbStructInfo = sizeof(int);
4773 return TRUE;
4775 __TRY
4777 if (pbEncoded[0] == ASN_ENUMERATED)
4779 unsigned int val = 0, i;
4781 if (cbEncoded <= 1)
4783 SetLastError(CRYPT_E_ASN1_EOD);
4784 ret = FALSE;
4786 else if (pbEncoded[1] == 0)
4788 SetLastError(CRYPT_E_ASN1_CORRUPT);
4789 ret = FALSE;
4791 else
4793 /* A little strange looking, but we have to accept a sign byte:
4794 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4795 * assuming a small length is okay here, it has to be in short
4796 * form.
4798 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4800 SetLastError(CRYPT_E_ASN1_LARGE);
4801 return FALSE;
4803 for (i = 0; i < pbEncoded[1]; i++)
4805 val <<= 8;
4806 val |= pbEncoded[2 + i];
4808 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4809 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4811 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4812 pvStructInfo = *(BYTE **)pvStructInfo;
4813 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4817 else
4819 SetLastError(CRYPT_E_ASN1_BADTAG);
4820 ret = FALSE;
4823 __EXCEPT_PAGE_FAULT
4825 SetLastError(STATUS_ACCESS_VIOLATION);
4826 ret = FALSE;
4828 __ENDTRY
4829 return ret;
4832 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4833 * if it fails.
4835 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4836 do { \
4837 BYTE i; \
4839 (word) = 0; \
4840 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4842 if (!isdigit(*(pbEncoded))) \
4844 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4845 ret = FALSE; \
4847 else \
4849 (word) *= 10; \
4850 (word) += *(pbEncoded)++ - '0'; \
4853 } while (0)
4855 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4856 SYSTEMTIME *sysTime)
4858 BOOL ret = TRUE;
4860 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4862 WORD hours, minutes = 0;
4863 BYTE sign = *pbEncoded++;
4865 len--;
4866 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4867 if (ret && hours >= 24)
4869 SetLastError(CRYPT_E_ASN1_CORRUPT);
4870 ret = FALSE;
4872 else if (len >= 2)
4874 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4875 if (ret && minutes >= 60)
4877 SetLastError(CRYPT_E_ASN1_CORRUPT);
4878 ret = FALSE;
4881 if (ret)
4883 if (sign == '+')
4885 sysTime->wHour += hours;
4886 sysTime->wMinute += minutes;
4888 else
4890 if (hours > sysTime->wHour)
4892 sysTime->wDay--;
4893 sysTime->wHour = 24 - (hours - sysTime->wHour);
4895 else
4896 sysTime->wHour -= hours;
4897 if (minutes > sysTime->wMinute)
4899 sysTime->wHour--;
4900 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4902 else
4903 sysTime->wMinute -= minutes;
4907 return ret;
4910 #define MIN_ENCODED_TIME_LENGTH 10
4912 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4913 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4914 DWORD *pcbDecoded)
4916 BOOL ret = FALSE;
4918 if (pbEncoded[0] == ASN_UTCTIME)
4920 if (cbEncoded <= 1)
4921 SetLastError(CRYPT_E_ASN1_EOD);
4922 else if (pbEncoded[1] > 0x7f)
4924 /* long-form date strings really can't be valid */
4925 SetLastError(CRYPT_E_ASN1_CORRUPT);
4927 else
4929 SYSTEMTIME sysTime = { 0 };
4930 BYTE len = pbEncoded[1];
4932 if (len < MIN_ENCODED_TIME_LENGTH)
4933 SetLastError(CRYPT_E_ASN1_CORRUPT);
4934 else
4936 ret = TRUE;
4937 if (pcbDecoded)
4938 *pcbDecoded = 2 + len;
4939 pbEncoded += 2;
4940 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4941 if (sysTime.wYear >= 50)
4942 sysTime.wYear += 1900;
4943 else
4944 sysTime.wYear += 2000;
4945 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4946 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4947 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4948 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4949 if (ret && len > 0)
4951 if (len >= 2 && isdigit(*pbEncoded) &&
4952 isdigit(*(pbEncoded + 1)))
4953 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4954 sysTime.wSecond);
4955 else if (isdigit(*pbEncoded))
4956 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4957 sysTime.wSecond);
4958 if (ret)
4959 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4960 &sysTime);
4962 if (ret)
4964 if (!pvStructInfo)
4965 *pcbStructInfo = sizeof(FILETIME);
4966 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4967 sizeof(FILETIME))))
4968 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4973 else
4974 SetLastError(CRYPT_E_ASN1_BADTAG);
4975 return ret;
4978 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4979 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4980 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4982 BOOL ret = FALSE;
4984 __TRY
4986 DWORD bytesNeeded = 0;
4988 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4989 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4990 if (ret)
4992 if (!pvStructInfo)
4993 *pcbStructInfo = bytesNeeded;
4994 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4995 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4997 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4998 pvStructInfo = *(BYTE **)pvStructInfo;
4999 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
5000 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5001 &bytesNeeded, NULL);
5002 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5003 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
5007 __EXCEPT_PAGE_FAULT
5009 SetLastError(STATUS_ACCESS_VIOLATION);
5011 __ENDTRY
5012 return ret;
5015 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
5016 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5017 DWORD *pcbDecoded)
5019 BOOL ret = FALSE;
5021 if (pbEncoded[0] == ASN_GENERALTIME)
5023 if (cbEncoded <= 1)
5024 SetLastError(CRYPT_E_ASN1_EOD);
5025 else if (pbEncoded[1] > 0x7f)
5027 /* long-form date strings really can't be valid */
5028 SetLastError(CRYPT_E_ASN1_CORRUPT);
5030 else
5032 BYTE len = pbEncoded[1];
5034 if (len < MIN_ENCODED_TIME_LENGTH)
5035 SetLastError(CRYPT_E_ASN1_CORRUPT);
5036 else
5038 SYSTEMTIME sysTime = { 0 };
5040 ret = TRUE;
5041 if (pcbDecoded)
5042 *pcbDecoded = 2 + len;
5043 pbEncoded += 2;
5044 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
5045 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
5046 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
5047 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
5048 if (ret && len > 0)
5050 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5051 sysTime.wMinute);
5052 if (ret && len > 0)
5053 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5054 sysTime.wSecond);
5055 if (ret && len > 0 && (*pbEncoded == '.' ||
5056 *pbEncoded == ','))
5058 BYTE digits;
5060 pbEncoded++;
5061 len--;
5062 /* workaround macro weirdness */
5063 digits = min(len, 3);
5064 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
5065 sysTime.wMilliseconds);
5067 if (ret)
5068 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
5069 &sysTime);
5071 if (ret)
5073 if (!pvStructInfo)
5074 *pcbStructInfo = sizeof(FILETIME);
5075 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
5076 sizeof(FILETIME))))
5077 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
5082 else
5083 SetLastError(CRYPT_E_ASN1_BADTAG);
5084 return ret;
5087 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
5088 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5089 DWORD *pcbDecoded)
5091 BOOL ret;
5092 InternalDecodeFunc decode = NULL;
5094 if (pbEncoded[0] == ASN_UTCTIME)
5095 decode = CRYPT_AsnDecodeUtcTimeInternal;
5096 else if (pbEncoded[0] == ASN_GENERALTIME)
5097 decode = CRYPT_AsnDecodeGeneralizedTime;
5098 if (decode)
5099 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
5100 pcbStructInfo, pcbDecoded);
5101 else
5103 SetLastError(CRYPT_E_ASN1_BADTAG);
5104 ret = FALSE;
5106 return ret;
5109 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
5110 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5111 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5113 BOOL ret;
5115 __TRY
5117 DWORD bytesNeeded = 0;
5119 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
5120 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
5121 if (ret)
5123 if (!pvStructInfo)
5124 *pcbStructInfo = bytesNeeded;
5125 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5126 pvStructInfo, pcbStructInfo, bytesNeeded)))
5128 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5129 pvStructInfo = *(BYTE **)pvStructInfo;
5130 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
5131 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5132 &bytesNeeded, NULL);
5133 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5134 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
5138 __EXCEPT_PAGE_FAULT
5140 SetLastError(STATUS_ACCESS_VIOLATION);
5141 ret = FALSE;
5143 __ENDTRY
5144 return ret;
5147 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
5148 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5149 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5151 BOOL ret = TRUE;
5153 __TRY
5155 if (pbEncoded[0] == ASN_SEQUENCEOF)
5157 DWORD bytesNeeded, dataLen, remainingLen, cValue;
5159 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5161 BYTE lenBytes;
5162 const BYTE *ptr;
5164 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5165 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
5166 cValue = 0;
5167 ptr = pbEncoded + 1 + lenBytes;
5168 remainingLen = dataLen;
5169 while (ret && remainingLen)
5171 DWORD nextLen;
5173 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5174 if (ret)
5176 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5178 remainingLen -= 1 + nextLenBytes + nextLen;
5179 ptr += 1 + nextLenBytes + nextLen;
5180 bytesNeeded += sizeof(CRYPT_DER_BLOB);
5181 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
5182 bytesNeeded += 1 + nextLenBytes + nextLen;
5183 cValue++;
5186 if (ret)
5188 CRYPT_SEQUENCE_OF_ANY *seq;
5189 BYTE *nextPtr;
5190 DWORD i;
5192 if (!pvStructInfo)
5193 *pcbStructInfo = bytesNeeded;
5194 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5195 pvStructInfo, pcbStructInfo, bytesNeeded)))
5197 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5198 pvStructInfo = *(BYTE **)pvStructInfo;
5199 seq = pvStructInfo;
5200 seq->cValue = cValue;
5201 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
5202 sizeof(*seq));
5203 nextPtr = (BYTE *)seq->rgValue +
5204 cValue * sizeof(CRYPT_DER_BLOB);
5205 ptr = pbEncoded + 1 + lenBytes;
5206 remainingLen = dataLen;
5207 i = 0;
5208 while (ret && remainingLen)
5210 DWORD nextLen;
5212 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5213 if (ret)
5215 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5217 seq->rgValue[i].cbData = 1 + nextLenBytes +
5218 nextLen;
5219 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
5220 seq->rgValue[i].pbData = (BYTE *)ptr;
5221 else
5223 seq->rgValue[i].pbData = nextPtr;
5224 memcpy(nextPtr, ptr, 1 + nextLenBytes +
5225 nextLen);
5226 nextPtr += 1 + nextLenBytes + nextLen;
5228 remainingLen -= 1 + nextLenBytes + nextLen;
5229 ptr += 1 + nextLenBytes + nextLen;
5230 i++;
5233 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5234 CRYPT_FreeSpace(pDecodePara, seq);
5239 else
5241 SetLastError(CRYPT_E_ASN1_BADTAG);
5242 ret = FALSE;
5245 __EXCEPT_PAGE_FAULT
5247 SetLastError(STATUS_ACCESS_VIOLATION);
5248 ret = FALSE;
5250 __ENDTRY
5251 return ret;
5254 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
5255 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5256 DWORD *pcbDecoded)
5258 BOOL ret;
5260 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
5262 DWORD bytesNeeded = 0, dataLen;
5264 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5266 struct AsnArrayDescriptor arrayDesc = {
5267 ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5268 offsetof(CRL_DIST_POINT_NAME, FullName.cAltEntry),
5269 offsetof(CRL_DIST_POINT_NAME, FullName.rgAltEntry),
5270 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, FullName),
5271 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
5272 offsetof(CERT_ALT_NAME_ENTRY, pwszURL) };
5273 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5274 DWORD nameLen;
5276 if (dataLen)
5278 ret = CRYPT_AsnDecodeArray(&arrayDesc,
5279 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
5280 dwFlags, NULL, NULL, &nameLen, NULL);
5281 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
5282 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, FullName);
5284 else
5285 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
5286 if (pcbDecoded)
5287 *pcbDecoded = 1 + lenBytes + dataLen;
5288 if (!pvStructInfo)
5289 *pcbStructInfo = bytesNeeded;
5290 else if (*pcbStructInfo < bytesNeeded)
5292 *pcbStructInfo = bytesNeeded;
5293 SetLastError(ERROR_MORE_DATA);
5294 ret = FALSE;
5296 else
5298 CRL_DIST_POINT_NAME *name = pvStructInfo;
5300 *pcbStructInfo = bytesNeeded;
5301 if (dataLen)
5303 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
5304 ret = CRYPT_AsnDecodeArray(&arrayDesc,
5305 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
5306 dwFlags, NULL, &name->FullName.cAltEntry, &nameLen,
5307 NULL);
5309 else
5310 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
5314 else
5316 SetLastError(CRYPT_E_ASN1_BADTAG);
5317 ret = FALSE;
5319 return ret;
5322 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
5323 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5325 struct AsnDecodeSequenceItem items[] = {
5326 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
5327 DistPointName), CRYPT_AsnDecodeDistPointName,
5328 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
5329 DistPointName.FullName.rgAltEntry), 0 },
5330 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
5331 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
5332 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
5333 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
5334 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
5335 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
5337 CRL_DIST_POINT *point = pvStructInfo;
5338 BOOL ret;
5340 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5341 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5342 pcbDecoded, point ? point->DistPointName.FullName.rgAltEntry : NULL);
5343 return ret;
5346 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
5347 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5348 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5350 BOOL ret;
5352 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5353 pDecodePara, pvStructInfo, *pcbStructInfo);
5355 __TRY
5357 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5358 offsetof(CRL_DIST_POINTS_INFO, cDistPoint),
5359 offsetof(CRL_DIST_POINTS_INFO, rgDistPoint),
5360 sizeof(CRL_DIST_POINTS_INFO),
5361 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
5362 offsetof(CRL_DIST_POINT, DistPointName.FullName.rgAltEntry) };
5363 CRL_DIST_POINTS_INFO *info = pvStructInfo;
5365 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5366 info->rgDistPoint = (CRL_DIST_POINT *)(info + 1);
5367 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5368 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
5370 __EXCEPT_PAGE_FAULT
5372 SetLastError(STATUS_ACCESS_VIOLATION);
5373 ret = FALSE;
5375 __ENDTRY
5376 return ret;
5379 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
5380 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5381 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5383 BOOL ret;
5385 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5386 pDecodePara, pvStructInfo, *pcbStructInfo);
5388 __TRY
5390 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5391 offsetof(CERT_ENHKEY_USAGE, cUsageIdentifier),
5392 offsetof(CERT_ENHKEY_USAGE, rgpszUsageIdentifier),
5393 sizeof(CERT_ENHKEY_USAGE),
5394 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
5395 CERT_ENHKEY_USAGE *usage = pvStructInfo;
5397 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5398 usage->rgpszUsageIdentifier = (LPSTR *)(usage + 1);
5399 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5400 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
5402 __EXCEPT_PAGE_FAULT
5404 SetLastError(STATUS_ACCESS_VIOLATION);
5405 ret = FALSE;
5407 __ENDTRY
5408 return ret;
5411 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
5412 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5413 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5415 BOOL ret;
5417 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5418 pDecodePara, pvStructInfo, *pcbStructInfo);
5420 __TRY
5422 struct AsnDecodeSequenceItem items[] = {
5423 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
5424 DistPointName), CRYPT_AsnDecodeDistPointName,
5425 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
5426 offsetof(CRL_ISSUING_DIST_POINT,
5427 DistPointName.FullName.rgAltEntry), 0 },
5428 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
5429 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5430 FALSE, 0 },
5431 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
5432 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5433 FALSE, 0 },
5434 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
5435 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
5436 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
5437 OnlySomeReasonFlags.pbData), 0 },
5438 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
5439 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
5442 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5443 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5444 pcbStructInfo, NULL, NULL);
5446 __EXCEPT_PAGE_FAULT
5448 SetLastError(STATUS_ACCESS_VIOLATION);
5449 ret = FALSE;
5451 __ENDTRY
5452 return ret;
5455 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
5456 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5457 DWORD *pcbDecoded)
5459 BOOL ret;
5460 DWORD max, size = sizeof(max);
5462 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5463 pvStructInfo, *pcbStructInfo, pcbDecoded);
5465 if (!cbEncoded)
5467 SetLastError(CRYPT_E_ASN1_EOD);
5468 return FALSE;
5470 if (pbEncoded[0] != (ASN_CONTEXT | 1))
5472 SetLastError(CRYPT_E_ASN1_BADTAG);
5473 return FALSE;
5475 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
5476 &max, &size, pcbDecoded)))
5478 DWORD bytesNeeded = FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum);
5480 if (!pvStructInfo)
5481 *pcbStructInfo = bytesNeeded;
5482 else if (*pcbStructInfo < bytesNeeded)
5484 *pcbStructInfo = bytesNeeded;
5485 SetLastError(ERROR_MORE_DATA);
5486 ret = FALSE;
5488 else
5490 CERT_GENERAL_SUBTREE *subtree = CONTAINING_RECORD(pvStructInfo,
5491 CERT_GENERAL_SUBTREE, fMaximum);
5493 *pcbStructInfo = bytesNeeded;
5494 /* The BOOL is implicit: if the integer is present, then it's
5495 * TRUE.
5497 subtree->fMaximum = TRUE;
5498 subtree->dwMaximum = max;
5501 TRACE("returning %d\n", ret);
5502 return ret;
5505 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
5506 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5507 DWORD *pcbDecoded)
5509 BOOL ret;
5510 struct AsnDecodeSequenceItem items[] = {
5511 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
5512 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
5513 offsetof(CERT_ALT_NAME_ENTRY, pwszURL), 0 },
5514 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
5515 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
5516 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
5517 CRYPT_AsnDecodeMaximum, FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum),
5518 TRUE, FALSE, 0, 0 },
5520 CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
5522 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5523 pvStructInfo, *pcbStructInfo, pcbDecoded);
5525 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5526 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5527 pcbDecoded, subtree ? subtree->Base.pwszURL : NULL);
5528 if (pcbDecoded)
5530 TRACE("%ld\n", *pcbDecoded);
5531 if (*pcbDecoded < cbEncoded)
5532 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
5533 *(pbEncoded + *pcbDecoded + 1));
5535 TRACE("returning %d\n", ret);
5536 return ret;
5539 static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
5540 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5541 DWORD *pcbDecoded)
5543 BOOL ret = TRUE;
5544 struct AsnArrayDescriptor arrayDesc = { 0,
5545 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5546 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree),
5547 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5548 cExcludedSubtree),
5549 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5550 offsetof(CERT_GENERAL_SUBTREE, Base.pwszURL) };
5552 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5553 pvStructInfo, *pcbStructInfo, pcbDecoded);
5555 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5556 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5557 return ret;
5560 static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
5561 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5562 DWORD *pcbDecoded)
5564 BOOL ret = TRUE;
5565 struct AsnArrayDescriptor arrayDesc = { 0,
5566 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5567 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree),
5568 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5569 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5570 offsetof(CERT_GENERAL_SUBTREE, Base.pwszURL) };
5572 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5573 pvStructInfo, *pcbStructInfo, pcbDecoded);
5575 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5576 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5577 return ret;
5580 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
5581 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5582 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5584 BOOL ret = FALSE;
5586 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5587 pDecodePara, pvStructInfo, *pcbStructInfo);
5589 __TRY
5591 struct AsnDecodeSequenceItem items[] = {
5592 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5593 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5594 CRYPT_AsnDecodePermittedSubtree,
5595 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5596 cExcludedSubtree), TRUE, TRUE,
5597 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
5598 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
5599 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5600 CRYPT_AsnDecodeExcludedSubtree,
5601 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5602 TRUE, TRUE,
5603 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
5606 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5607 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5608 pcbStructInfo, NULL, NULL);
5610 __EXCEPT_PAGE_FAULT
5612 SetLastError(STATUS_ACCESS_VIOLATION);
5614 __ENDTRY
5615 return ret;
5618 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
5619 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5620 DWORD *pcbDecoded)
5622 BOOL ret;
5623 struct AsnDecodeSequenceItem items[] = {
5624 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
5625 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
5626 Issuer.pbData) },
5627 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
5628 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
5629 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
5631 CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
5633 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5634 pvStructInfo, *pcbStructInfo, pcbDecoded);
5636 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5637 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5638 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
5639 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
5641 SetLastError(CRYPT_E_ASN1_CORRUPT);
5642 ret = FALSE;
5644 TRACE("returning %d\n", ret);
5645 return ret;
5648 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
5649 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5650 DWORD *pcbDecoded)
5652 CMSG_SIGNER_INFO *info = pvStructInfo;
5653 struct AsnDecodeSequenceItem items[] = {
5654 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
5655 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5656 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
5657 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
5658 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
5659 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
5660 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5661 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5662 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5663 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
5664 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5665 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5666 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
5667 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5668 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
5669 HashEncryptionAlgorithm.pszObjId), 0 },
5670 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
5671 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
5672 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
5673 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5674 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
5675 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5676 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5678 BOOL ret;
5680 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5681 pvStructInfo, *pcbStructInfo);
5683 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5684 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5685 pcbDecoded, info ? info->Issuer.pbData : NULL);
5686 return ret;
5689 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
5690 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5691 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5693 BOOL ret = FALSE;
5695 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5696 pDecodePara, pvStructInfo, *pcbStructInfo);
5698 __TRY
5700 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
5701 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5702 if (ret && pvStructInfo)
5704 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5705 pcbStructInfo, *pcbStructInfo);
5706 if (ret)
5708 CMSG_SIGNER_INFO *info;
5710 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5711 pvStructInfo = *(BYTE **)pvStructInfo;
5712 info = pvStructInfo;
5713 info->Issuer.pbData = ((BYTE *)info +
5714 sizeof(CMSG_SIGNER_INFO));
5715 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
5716 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5717 pcbStructInfo, NULL);
5718 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5719 CRYPT_FreeSpace(pDecodePara, info);
5723 __EXCEPT_PAGE_FAULT
5725 SetLastError(STATUS_ACCESS_VIOLATION);
5727 __ENDTRY
5728 TRACE("returning %d\n", ret);
5729 return ret;
5732 static BOOL verify_and_copy_certificate(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5733 void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5735 PCCERT_CONTEXT cert;
5737 cert = CertCreateCertificateContext(X509_ASN_ENCODING, pbEncoded, cbEncoded);
5738 if (!cert)
5740 WARN("CertCreateCertificateContext error %#lx\n", GetLastError());
5741 *pcbStructInfo = 0;
5742 *pcbDecoded = 0;
5743 return TRUE;
5746 CertFreeCertificateContext(cert);
5748 return CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, pcbDecoded);
5751 static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
5752 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5753 DWORD *pcbDecoded)
5755 BOOL ret;
5756 struct AsnArrayDescriptor arrayDesc = { 0,
5757 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
5758 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded),
5759 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded),
5760 verify_and_copy_certificate,
5761 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5763 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5764 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5766 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5767 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5768 return ret;
5771 static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
5772 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5773 DWORD *pcbDecoded)
5775 BOOL ret;
5776 struct AsnArrayDescriptor arrayDesc = { 0,
5777 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded),
5778 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded),
5779 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content),
5780 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB),
5781 TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5783 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5784 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5786 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5787 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5788 return ret;
5791 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
5792 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5793 DWORD *pcbDecoded)
5795 CERT_ID *id = pvStructInfo;
5796 BOOL ret = FALSE;
5798 if (*pbEncoded == ASN_SEQUENCEOF)
5800 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
5801 id ? &id->IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
5802 if (ret)
5804 if (id)
5805 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5806 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
5807 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5808 sizeof(CERT_ISSUER_SERIAL_NUMBER);
5809 else
5810 *pcbStructInfo = sizeof(CERT_ID);
5813 else if (*pbEncoded == (ASN_CONTEXT | 0))
5815 ret = CRYPT_AsnDecodeOctets(pbEncoded, cbEncoded, dwFlags,
5816 id ? &id->KeyId : NULL, pcbStructInfo, pcbDecoded);
5817 if (ret)
5819 if (id)
5820 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
5821 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
5822 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5823 sizeof(CRYPT_DATA_BLOB);
5824 else
5825 *pcbStructInfo = sizeof(CERT_ID);
5828 else
5829 SetLastError(CRYPT_E_ASN1_BADTAG);
5830 return ret;
5833 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5834 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5835 DWORD *pcbDecoded)
5837 CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
5838 struct AsnDecodeSequenceItem items[] = {
5839 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5840 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5841 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5842 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5843 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.KeyId.pbData), 0 },
5844 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5845 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5846 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5847 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5848 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5849 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5850 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5851 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5852 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5853 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5854 HashEncryptionAlgorithm.pszObjId), 0 },
5855 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5856 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
5857 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5858 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5859 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5860 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5861 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5863 BOOL ret;
5865 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5866 pvStructInfo, *pcbStructInfo);
5868 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5869 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5870 pcbDecoded, info ? info->SignerId.KeyId.pbData : NULL);
5871 return ret;
5874 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5875 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5876 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5878 BOOL ret = FALSE;
5880 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5881 pDecodePara, pvStructInfo, *pcbStructInfo);
5883 __TRY
5885 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5886 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5887 if (ret && pvStructInfo)
5889 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5890 pcbStructInfo, *pcbStructInfo);
5891 if (ret)
5893 CMSG_CMS_SIGNER_INFO *info;
5895 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5896 pvStructInfo = *(BYTE **)pvStructInfo;
5897 info = pvStructInfo;
5898 info->SignerId.KeyId.pbData = ((BYTE *)info +
5899 sizeof(CMSG_CMS_SIGNER_INFO));
5900 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5901 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5902 pcbStructInfo, NULL);
5903 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5904 CRYPT_FreeSpace(pDecodePara, info);
5908 __EXCEPT_PAGE_FAULT
5910 SetLastError(STATUS_ACCESS_VIOLATION);
5912 __ENDTRY
5913 TRACE("returning %d\n", ret);
5914 return ret;
5917 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5918 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5920 BOOL ret;
5921 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5922 offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5923 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo),
5924 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo),
5925 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5926 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.KeyId.pbData) };
5928 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5929 pvStructInfo, *pcbStructInfo, pcbDecoded);
5931 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5932 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5933 return ret;
5936 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5937 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5938 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5940 BOOL ret = FALSE;
5941 struct AsnDecodeSequenceItem items[] = {
5942 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5943 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5944 /* Placeholder for the hash algorithms - redundant with those in the
5945 * signers, so just ignore them.
5947 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5948 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5949 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5950 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5951 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5952 offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
5953 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
5954 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5955 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5956 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
5957 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
5958 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5959 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5960 CRYPT_DecodeSignerArray,
5961 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE,
5962 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5965 TRACE("%p, %ld, %08lx, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags,
5966 pDecodePara, signedInfo, pcbSignedInfo);
5968 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5969 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5970 NULL, NULL);
5971 TRACE("returning %d\n", ret);
5972 return ret;
5975 static BOOL CRYPT_AsnDecodeRecipientInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5976 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5978 BOOL ret;
5979 CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
5980 struct AsnDecodeSequenceItem items[] = {
5981 { ASN_INTEGER, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, dwVersion),
5982 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5983 { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5984 RecipientId.IssuerSerialNumber), CRYPT_AsnDecodeIssuerSerialNumber,
5985 sizeof(CERT_ISSUER_SERIAL_NUMBER), FALSE, TRUE,
5986 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5987 RecipientId.IssuerSerialNumber.Issuer.pbData), 0 },
5988 { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5989 KeyEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
5990 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
5991 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5992 KeyEncryptionAlgorithm.pszObjId), 0 },
5993 { ASN_OCTETSTRING, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey),
5994 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
5995 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey.pbData), 0 },
5998 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5999 pvStructInfo, *pcbStructInfo, pcbDecoded);
6001 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6002 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
6003 pcbDecoded, info ? info->RecipientId.IssuerSerialNumber.Issuer.pbData :
6004 NULL);
6005 if (info)
6006 info->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6007 TRACE("returning %d\n", ret);
6008 return ret;
6011 static BOOL CRYPT_DecodeRecipientInfoArray(const BYTE *pbEncoded,
6012 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6013 DWORD *pcbDecoded)
6015 BOOL ret;
6016 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
6017 offsetof(CRYPT_ENVELOPED_DATA, cRecipientInfo),
6018 offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo),
6019 MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
6020 CRYPT_AsnDecodeRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), TRUE,
6021 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
6022 RecipientId.IssuerSerialNumber.Issuer.pbData) };
6024 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
6025 pvStructInfo, *pcbStructInfo, pcbDecoded);
6027 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
6028 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
6029 TRACE("returning %d\n", ret);
6030 return ret;
6033 static BOOL CRYPT_AsnDecodeEncryptedContentInfo(const BYTE *pbEncoded,
6034 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6035 DWORD *pcbDecoded)
6037 BOOL ret;
6038 CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
6039 struct AsnDecodeSequenceItem items[] = {
6040 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6041 contentType), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
6042 FALSE, TRUE, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6043 contentType), 0 },
6044 { ASN_SEQUENCEOF, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6045 contentEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
6046 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
6047 offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6048 contentEncryptionAlgorithm.pszObjId), 0 },
6049 { ASN_CONTEXT | 0, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6050 encryptedContent), CRYPT_AsnDecodeOctets,
6051 sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
6052 offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, encryptedContent.pbData) },
6055 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
6056 pvStructInfo, *pcbStructInfo, pcbDecoded);
6058 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6059 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
6060 pcbDecoded, info ? info->contentType : NULL);
6061 TRACE("returning %d\n", ret);
6062 return ret;
6065 BOOL CRYPT_AsnDecodePKCSEnvelopedData(const BYTE *pbEncoded, DWORD cbEncoded,
6066 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
6067 CRYPT_ENVELOPED_DATA *envelopedData, DWORD *pcbEnvelopedData)
6069 BOOL ret;
6070 struct AsnDecodeSequenceItem items[] = {
6071 { ASN_INTEGER, offsetof(CRYPT_ENVELOPED_DATA, version),
6072 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
6073 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ENVELOPED_DATA,
6074 cRecipientInfo), CRYPT_DecodeRecipientInfoArray,
6075 MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
6076 FALSE, TRUE, offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo), 0 },
6077 { ASN_SEQUENCEOF, offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo),
6078 CRYPT_AsnDecodeEncryptedContentInfo,
6079 sizeof(CRYPT_ENCRYPTED_CONTENT_INFO), FALSE, TRUE,
6080 offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo.contentType), 0 },
6083 TRACE("%p, %ld, %08lx, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags,
6084 pDecodePara, envelopedData, pcbEnvelopedData);
6086 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6087 pbEncoded, cbEncoded, dwFlags, pDecodePara, envelopedData,
6088 pcbEnvelopedData, NULL, NULL);
6089 TRACE("returning %d\n", ret);
6090 return ret;
6093 static BOOL WINAPI CRYPT_AsnDecodeObjectIdentifier(DWORD dwCertEncodingType,
6094 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6095 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6097 DWORD bytesNeeded = 0;
6098 BOOL ret;
6100 __TRY
6102 ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
6103 NULL, &bytesNeeded, NULL);
6104 if (ret)
6106 if (!pvStructInfo)
6107 *pcbStructInfo = bytesNeeded;
6108 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
6110 LPSTR *info;
6112 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6113 pvStructInfo = *(BYTE **)pvStructInfo;
6115 info = pvStructInfo;
6116 *info = (void *)((BYTE *)info + sizeof(*info));
6117 ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
6118 pvStructInfo, &bytesNeeded, NULL);
6119 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
6120 CRYPT_FreeSpace(pDecodePara, info);
6124 __EXCEPT_PAGE_FAULT
6126 SetLastError(STATUS_ACCESS_VIOLATION);
6127 ret = FALSE;
6129 __ENDTRY
6130 return ret;
6133 static BOOL WINAPI CRYPT_AsnDecodeEccSignature(DWORD dwCertEncodingType,
6134 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6135 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6137 BOOL ret;
6138 struct AsnDecodeSequenceItem items[] = {
6139 { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, r),
6140 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE,
6141 TRUE, offsetof(CERT_ECC_SIGNATURE, r.pbData), 0 },
6142 { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, s),
6143 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE,
6144 TRUE, offsetof(CERT_ECC_SIGNATURE, s.pbData), 0 },
6147 __TRY
6149 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6150 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6151 pcbStructInfo, NULL, NULL);
6153 __EXCEPT_PAGE_FAULT
6155 SetLastError(STATUS_ACCESS_VIOLATION);
6156 ret = FALSE;
6158 __ENDTRY
6159 return ret;
6162 static BOOL CRYPT_AsnDecodeOCSPResponseStatus(const BYTE *pbEncoded,
6163 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6164 DWORD *pcbDecoded)
6166 if (!cbEncoded)
6168 SetLastError(CRYPT_E_ASN1_EOD);
6169 return FALSE;
6171 if (pbEncoded[0] != ASN_ENUMERATED)
6173 SetLastError(CRYPT_E_ASN1_BADTAG);
6174 return FALSE;
6177 return CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
6178 pcbStructInfo, pcbDecoded);
6181 static BOOL CRYPT_AsnDecodeOCSPResponseBytes(const BYTE *pbEncoded,
6182 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6183 DWORD *pcbDecoded)
6185 DWORD dataLen;
6186 BOOL ret;
6188 if (!cbEncoded)
6190 SetLastError(CRYPT_E_ASN1_EOD);
6191 return FALSE;
6193 if (pbEncoded[0] != (ASN_CONTEXT | ASN_CONSTRUCTOR))
6195 SetLastError(CRYPT_E_ASN1_BADTAG);
6196 return FALSE;
6199 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
6201 struct AsnDecodeSequenceItem items[] = {
6202 { ASN_OBJECTIDENTIFIER, 0,
6203 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
6204 0, 0 },
6205 { ASN_OCTETSTRING, sizeof(LPSTR),
6206 CRYPT_AsnDecodeOctets, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
6207 sizeof(LPSTR) + offsetof(CRYPT_OBJID_BLOB, pbData), 0 },
6209 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6210 DWORD bytesNeeded;
6212 if (dataLen)
6214 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6215 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, dwFlags, NULL,
6216 pvStructInfo, pcbStructInfo, &bytesNeeded, NULL);
6217 if (ret) *pcbDecoded = bytesNeeded + lenBytes + 1;
6220 return ret;
6223 static BOOL WINAPI CRYPT_AsnDecodeOCSPResponse(DWORD dwCertEncodingType,
6224 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6225 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6227 BOOL ret;
6228 struct AsnDecodeSequenceItem items[] = {
6229 { ASN_ENUMERATED, offsetof(OCSP_RESPONSE_INFO, dwStatus),
6230 CRYPT_AsnDecodeOCSPResponseStatus, sizeof(DWORD), FALSE, FALSE,
6231 0, 0 },
6232 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(OCSP_RESPONSE_INFO, pszObjId),
6233 CRYPT_AsnDecodeOCSPResponseBytes, sizeof(LPSTR) + sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
6234 offsetof(OCSP_RESPONSE_INFO, pszObjId), 0 },
6237 __TRY
6239 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6240 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6241 pcbStructInfo, NULL, NULL);
6243 __EXCEPT_PAGE_FAULT
6245 SetLastError(STATUS_ACCESS_VIOLATION);
6246 ret = FALSE;
6248 __ENDTRY
6249 return ret;
6252 static BOOL CRYPT_AsnDecodeOCSPSignatureInfoCertEncoded(const BYTE *pbEncoded,
6253 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6254 DWORD *pcbDecoded)
6256 BOOL ret;
6257 struct AsnArrayDescriptor arrayDesc = { 0,
6258 offsetof(OCSP_SIGNATURE_INFO, cCertEncoded), offsetof(OCSP_SIGNATURE_INFO, rgCertEncoded),
6259 FINALMEMBERSIZE(OCSP_SIGNATURE_INFO, cCertEncoded), verify_and_copy_certificate,
6260 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
6262 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
6263 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
6264 return ret;
6267 static BOOL WINAPI CRYPT_AsnDecodeOCSPBasicSignedResponse(DWORD dwCertEncodingType,
6268 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6269 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6271 BOOL ret;
6272 struct AsnDecodeSequenceItem items[] = {
6273 { 0, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, ToBeSigned),
6274 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
6275 offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, ToBeSigned.pbData), 0 },
6276 { ASN_SEQUENCEOF, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.SignatureAlgorithm),
6277 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
6278 offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.SignatureAlgorithm.pszObjId), 0 },
6279 { ASN_BITSTRING, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.Signature),
6280 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
6281 offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.Signature.pbData) },
6282 { 0, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.cCertEncoded),
6283 CRYPT_AsnDecodeOCSPSignatureInfoCertEncoded, FINALMEMBERSIZE(OCSP_SIGNATURE_INFO, cCertEncoded),
6284 TRUE, TRUE, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.rgCertEncoded) },
6287 __TRY
6289 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6290 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6291 pcbStructInfo, NULL, NULL);
6293 __EXCEPT_PAGE_FAULT
6295 SetLastError(STATUS_ACCESS_VIOLATION);
6296 ret = FALSE;
6298 __ENDTRY
6299 return ret;
6302 static BOOL CRYPT_AsnDecodeOCSPHashAlgorithm(const BYTE *pbEncoded,
6303 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6304 DWORD *pcbDecoded)
6306 DWORD dataLen;
6307 BOOL ret;
6309 if (!cbEncoded)
6311 SetLastError(CRYPT_E_ASN1_EOD);
6312 return FALSE;
6314 if (pbEncoded[0] != ASN_SEQUENCEOF)
6316 SetLastError(CRYPT_E_ASN1_BADTAG);
6317 return FALSE;
6320 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
6322 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6323 DWORD bytesDecoded;
6324 if (dataLen)
6326 ret = CRYPT_AsnDecodeAlgorithmId(pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, dwFlags,
6327 pvStructInfo, pcbStructInfo, &bytesDecoded);
6328 if (ret) *pcbDecoded = bytesDecoded + lenBytes + 1;
6331 return ret;
6334 static BOOL CRYPT_AsnDecodeOCSPNextUpdate(const BYTE *pbEncoded,
6335 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6336 DWORD *pcbDecoded)
6338 DWORD dataLen;
6339 BOOL ret;
6341 if (!cbEncoded)
6343 SetLastError(CRYPT_E_ASN1_EOD);
6344 return FALSE;
6346 if (pbEncoded[0] != (ASN_CONTEXT | ASN_CONSTRUCTOR))
6348 SetLastError(CRYPT_E_ASN1_BADTAG);
6349 return FALSE;
6352 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
6354 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6355 DWORD bytesDecoded;
6356 if (dataLen)
6358 ret = CRYPT_AsnDecodeGeneralizedTime(pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, dwFlags,
6359 pvStructInfo, pcbStructInfo, &bytesDecoded);
6360 if (ret) *pcbDecoded = bytesDecoded + lenBytes + 1;
6363 return ret;
6366 static BOOL CRYPT_AsnDecodeCertStatus(const BYTE *pbEncoded,
6367 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6368 DWORD *pcbDecoded)
6370 BOOL ret = TRUE;
6371 BYTE tag = pbEncoded[0] & ~3, status = pbEncoded[0] & 3;
6372 DWORD bytesNeeded = FIELD_OFFSET(OCSP_BASIC_RESPONSE_ENTRY, ThisUpdate) -
6373 FIELD_OFFSET(OCSP_BASIC_RESPONSE_ENTRY, dwCertStatus);
6375 if (!cbEncoded)
6377 SetLastError(CRYPT_E_ASN1_EOD);
6378 return FALSE;
6381 switch (status)
6383 case 0:
6384 if (tag != ASN_CONTEXT)
6386 WARN("Unexpected tag %02x\n", tag);
6387 SetLastError(CRYPT_E_ASN1_BADTAG);
6388 return FALSE;
6390 if (cbEncoded < 2 || pbEncoded[1])
6392 SetLastError(CRYPT_E_ASN1_CORRUPT);
6393 return FALSE;
6395 if (!pvStructInfo)
6396 *pcbStructInfo = bytesNeeded;
6397 else if (*pcbStructInfo < bytesNeeded)
6399 *pcbStructInfo = bytesNeeded;
6400 SetLastError(ERROR_MORE_DATA);
6401 return FALSE;
6403 if (pvStructInfo)
6405 *(DWORD *)pvStructInfo = 0;
6406 *(OCSP_BASIC_REVOKED_INFO **)((char *)pvStructInfo
6407 + FIELD_OFFSET(OCSP_BASIC_RESPONSE_ENTRY, pRevokedInfo)
6408 - FIELD_OFFSET(OCSP_BASIC_RESPONSE_ENTRY, dwCertStatus)) = NULL;
6410 *pcbStructInfo = bytesNeeded;
6411 *pcbDecoded = 2;
6412 break;
6414 case 1:
6416 DWORD dataLen;
6418 if (tag != (ASN_CONTEXT | ASN_CONSTRUCTOR))
6420 WARN("Unexpected tag %02x\n", tag);
6421 SetLastError(CRYPT_E_ASN1_BADTAG);
6422 return FALSE;
6424 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
6426 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6427 DWORD bytesDecoded, size;
6428 FILETIME date;
6430 if (dataLen)
6432 size = sizeof(date);
6433 ret = CRYPT_AsnDecodeGeneralizedTime(pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
6434 dwFlags, &date, &size, &bytesDecoded);
6435 if (ret)
6437 OCSP_BASIC_REVOKED_INFO *info;
6439 bytesNeeded += sizeof(*info);
6440 if (!pvStructInfo)
6441 *pcbStructInfo = bytesNeeded;
6442 else if (*pcbStructInfo < bytesNeeded)
6444 *pcbStructInfo = bytesNeeded;
6445 SetLastError(ERROR_MORE_DATA);
6446 return FALSE;
6448 if (pvStructInfo)
6450 *(DWORD *)pvStructInfo = 1;
6451 info = *(OCSP_BASIC_REVOKED_INFO **)((char *)pvStructInfo
6452 + FIELD_OFFSET(OCSP_BASIC_RESPONSE_ENTRY, pRevokedInfo)
6453 - FIELD_OFFSET(OCSP_BASIC_RESPONSE_ENTRY, dwCertStatus));
6454 info->RevocationDate = date;
6456 *pcbStructInfo = bytesNeeded;
6457 *pcbDecoded = 1 + lenBytes + bytesDecoded;
6461 break;
6463 default:
6464 FIXME("Unhandled status %u\n", status);
6465 SetLastError(CRYPT_E_ASN1_BADTAG);
6466 return FALSE;
6469 return ret;
6472 static BOOL CRYPT_AsnDecodeOCSPBasicResponseEntry(const BYTE *pbEncoded, DWORD cbEncoded,
6473 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
6475 struct AsnDecodeSequenceItem items[] = {
6476 { ASN_SEQUENCEOF, offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.HashAlgorithm.pszObjId),
6477 CRYPT_AsnDecodeOCSPHashAlgorithm, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
6478 offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.HashAlgorithm.pszObjId), 0 },
6479 { ASN_OCTETSTRING, offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.IssuerNameHash),
6480 CRYPT_AsnDecodeOctets, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
6481 offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.IssuerNameHash.pbData), 0 },
6482 { ASN_OCTETSTRING, offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.IssuerKeyHash),
6483 CRYPT_AsnDecodeOctets, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
6484 offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.IssuerKeyHash.pbData), 0 },
6485 { ASN_INTEGER, offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.SerialNumber),
6486 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
6487 offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.SerialNumber.pbData), 0 },
6488 { 0, offsetof(OCSP_BASIC_RESPONSE_ENTRY, dwCertStatus),
6489 CRYPT_AsnDecodeCertStatus, sizeof(DWORD), FALSE, TRUE,
6490 offsetof(OCSP_BASIC_RESPONSE_ENTRY, pRevokedInfo), 0 },
6491 { ASN_GENERALTIME, offsetof(OCSP_BASIC_RESPONSE_ENTRY, ThisUpdate),
6492 CRYPT_AsnDecodeGeneralizedTime, sizeof(FILETIME), FALSE, FALSE,
6493 0, 0 },
6494 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(OCSP_BASIC_RESPONSE_ENTRY, NextUpdate),
6495 CRYPT_AsnDecodeOCSPNextUpdate, sizeof(FILETIME), TRUE, FALSE,
6496 0, 0 },
6497 { ASN_CONTEXT | ASN_CONSTRUCTOR /* FIXME */, offsetof(OCSP_BASIC_RESPONSE_ENTRY, cExtension),
6498 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(OCSP_BASIC_RESPONSE_ENTRY, cExtension),
6499 TRUE, TRUE, offsetof(OCSP_BASIC_RESPONSE_ENTRY, rgExtension), 0 },
6502 return CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6503 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo,
6504 pcbStructInfo, pcbDecoded, NULL);
6507 static BOOL CRYPT_AsnDecodeOCSPBasicResponseEntriesArray(const BYTE *pbEncoded,
6508 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6509 DWORD *pcbDecoded)
6511 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
6512 offsetof(OCSP_BASIC_RESPONSE_INFO, cResponseEntry), offsetof(OCSP_BASIC_RESPONSE_INFO, rgResponseEntry),
6513 MEMBERSIZE(OCSP_BASIC_RESPONSE_INFO, cResponseEntry, cExtension),
6514 CRYPT_AsnDecodeOCSPBasicResponseEntry, sizeof(OCSP_BASIC_RESPONSE_ENTRY),
6515 FALSE, 0 };
6517 return CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
6518 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
6521 static BOOL CRYPT_AsnDecodeResponderIDByName(const BYTE *pbEncoded,
6522 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6523 DWORD *pcbDecoded)
6525 OCSP_BASIC_RESPONSE_INFO *info = pvStructInfo;
6526 DWORD dataLen, decodedLen, lenBytes, bytesNeeded = sizeof(*info);
6527 BYTE tag = pbEncoded[0] & ~3;
6528 CERT_NAME_BLOB *blob;
6530 if (tag != (ASN_CONTEXT | ASN_CONSTRUCTOR))
6532 WARN("Unexpected tag %02x\n", tag);
6533 SetLastError(CRYPT_E_ASN1_BADTAG);
6534 return FALSE;
6537 if (!CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))
6538 return FALSE;
6539 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6540 cbEncoded -= 1 + lenBytes;
6542 if (dataLen > cbEncoded)
6544 SetLastError(CRYPT_E_ASN1_EOD);
6545 return FALSE;
6547 pbEncoded += 1 + lenBytes;
6548 decodedLen = 1 + lenBytes + dataLen;
6550 if (pbEncoded[0] != ASN_SEQUENCE)
6552 WARN("Unexpected tag %02x %02x\n", pbEncoded[0], pbEncoded[1]);
6553 SetLastError(CRYPT_E_ASN1_BADTAG);
6554 return FALSE;
6557 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += dataLen;
6558 if (pvStructInfo && *pcbStructInfo >= bytesNeeded)
6560 info->dwResponderIdChoice = 1;
6562 blob = &info->ByNameResponderId;
6563 blob->cbData = dataLen;
6564 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
6565 blob->pbData = (BYTE *)pbEncoded;
6566 else if (blob->cbData)
6568 blob->pbData = (BYTE *)(info + 1);
6569 memcpy(blob->pbData, pbEncoded, blob->cbData);
6573 if (pcbDecoded)
6574 *pcbDecoded = decodedLen;
6576 if (!pvStructInfo)
6578 *pcbStructInfo = bytesNeeded;
6579 return TRUE;
6582 if (*pcbStructInfo < bytesNeeded)
6584 SetLastError(ERROR_MORE_DATA);
6585 *pcbStructInfo = bytesNeeded;
6586 return FALSE;
6589 *pcbStructInfo = bytesNeeded;
6590 return TRUE;
6593 static BOOL CRYPT_AsnDecodeResponderIDByKey(const BYTE *pbEncoded,
6594 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6595 DWORD *pcbDecoded)
6597 OCSP_BASIC_RESPONSE_INFO *info = pvStructInfo;
6598 DWORD dataLen, decodedLen, lenBytes, bytesNeeded = sizeof(*info), len;
6599 BYTE tag = pbEncoded[0] & ~3;
6600 CRYPT_HASH_BLOB *blob;
6602 if (tag != (ASN_CONTEXT | ASN_CONSTRUCTOR))
6604 WARN("Unexpected tag %02x\n", tag);
6605 SetLastError(CRYPT_E_ASN1_BADTAG);
6606 return FALSE;
6609 if (!CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))
6610 return FALSE;
6611 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6612 cbEncoded -= 1 + lenBytes;
6613 decodedLen = 1 + lenBytes;
6615 if (dataLen > cbEncoded)
6617 SetLastError(CRYPT_E_ASN1_EOD);
6618 return FALSE;
6620 pbEncoded += 1 + lenBytes;
6621 if (pbEncoded[0] != ASN_OCTETSTRING)
6623 WARN("Unexpected tag %02x\n", pbEncoded[0]);
6624 SetLastError(CRYPT_E_ASN1_BADTAG);
6625 return FALSE;
6628 if (!CRYPT_GetLen(pbEncoded, cbEncoded, &len))
6629 return FALSE;
6630 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6631 decodedLen += 1 + lenBytes + len;
6632 cbEncoded -= 1 + lenBytes;
6634 if (len > cbEncoded)
6636 SetLastError(CRYPT_E_ASN1_EOD);
6637 return FALSE;
6639 pbEncoded += 1 + lenBytes;
6641 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += len;
6642 if (pvStructInfo && *pcbStructInfo >= bytesNeeded)
6644 info->dwResponderIdChoice = 2;
6645 blob = &info->ByKeyResponderId;
6646 blob->cbData = len;
6647 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
6648 blob->pbData = (BYTE *)pbEncoded;
6649 else if (blob->cbData)
6651 blob->pbData = (BYTE *)(info + 1);
6652 memcpy(blob->pbData, pbEncoded, blob->cbData);
6656 if (pcbDecoded)
6657 *pcbDecoded = decodedLen;
6659 if (!pvStructInfo)
6661 *pcbStructInfo = bytesNeeded;
6662 return TRUE;
6665 if (*pcbStructInfo < bytesNeeded)
6667 SetLastError(ERROR_MORE_DATA);
6668 *pcbStructInfo = bytesNeeded;
6669 return FALSE;
6672 *pcbStructInfo = bytesNeeded;
6673 return TRUE;
6676 static BOOL CRYPT_AsnDecodeResponderID(const BYTE *pbEncoded,
6677 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6678 DWORD *pcbDecoded)
6680 BYTE choice = pbEncoded[0] & 3;
6682 TRACE("choice %02x\n", choice);
6683 switch (choice)
6685 case 1:
6686 return CRYPT_AsnDecodeResponderIDByName(pbEncoded, cbEncoded, dwFlags,
6687 pvStructInfo, pcbStructInfo, pcbDecoded);
6688 case 2:
6689 return CRYPT_AsnDecodeResponderIDByKey(pbEncoded, cbEncoded, dwFlags,
6690 pvStructInfo, pcbStructInfo, pcbDecoded);
6691 default:
6692 WARN("Unexpected choice %02x\n", choice);
6693 SetLastError(CRYPT_E_ASN1_CORRUPT);
6694 return FALSE;
6698 static BOOL WINAPI CRYPT_AsnDecodeOCSPBasicResponse(DWORD dwCertEncodingType,
6699 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6700 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6702 struct AsnDecodeSequenceItem items[] = {
6703 { 0, 0,
6704 CRYPT_AsnDecodeResponderID, offsetof(OCSP_BASIC_RESPONSE_INFO, ProducedAt), FALSE, TRUE,
6705 offsetof(OCSP_BASIC_RESPONSE_INFO, ByNameResponderId.pbData), 0 },
6706 { ASN_GENERALTIME, offsetof(OCSP_BASIC_RESPONSE_INFO, ProducedAt),
6707 CRYPT_AsnDecodeGeneralizedTime, sizeof(FILETIME), FALSE, FALSE,
6708 0, 0 },
6709 { ASN_SEQUENCEOF, offsetof(OCSP_BASIC_RESPONSE_INFO, cResponseEntry),
6710 CRYPT_AsnDecodeOCSPBasicResponseEntriesArray, MEMBERSIZE(OCSP_BASIC_RESPONSE_INFO, cResponseEntry, cExtension),
6711 TRUE, TRUE, offsetof(OCSP_BASIC_RESPONSE_INFO, rgResponseEntry) },
6712 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(OCSP_BASIC_RESPONSE_INFO, cExtension),
6713 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(OCSP_BASIC_RESPONSE_INFO, cExtension),
6714 TRUE, TRUE, offsetof(OCSP_BASIC_RESPONSE_INFO, rgExtension), 0 },
6716 BOOL ret;
6718 __TRY
6720 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6721 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6722 pcbStructInfo, NULL, NULL);
6724 __EXCEPT_PAGE_FAULT
6726 SetLastError(STATUS_ACCESS_VIOLATION);
6727 ret = FALSE;
6729 __ENDTRY
6730 return ret;
6733 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
6734 LPCSTR lpszStructType)
6736 CryptDecodeObjectExFunc decodeFunc = NULL;
6738 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
6739 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
6741 SetLastError(ERROR_FILE_NOT_FOUND);
6742 return NULL;
6744 if (IS_INTOID(lpszStructType))
6746 switch (LOWORD(lpszStructType))
6748 case LOWORD(X509_CERT):
6749 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
6750 break;
6751 case LOWORD(X509_CERT_TO_BE_SIGNED):
6752 decodeFunc = CRYPT_AsnDecodeCert;
6753 break;
6754 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
6755 decodeFunc = CRYPT_AsnDecodeCRL;
6756 break;
6757 case LOWORD(X509_EXTENSIONS):
6758 decodeFunc = CRYPT_AsnDecodeExtensions;
6759 break;
6760 case LOWORD(X509_NAME_VALUE):
6761 decodeFunc = CRYPT_AsnDecodeNameValue;
6762 break;
6763 case LOWORD(X509_NAME):
6764 decodeFunc = CRYPT_AsnDecodeName;
6765 break;
6766 case LOWORD(X509_PUBLIC_KEY_INFO):
6767 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
6768 break;
6769 case LOWORD(X509_AUTHORITY_KEY_ID):
6770 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
6771 break;
6772 case LOWORD(X509_ALTERNATE_NAME):
6773 decodeFunc = CRYPT_AsnDecodeAltName;
6774 break;
6775 case LOWORD(X509_BASIC_CONSTRAINTS):
6776 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
6777 break;
6778 case LOWORD(X509_BASIC_CONSTRAINTS2):
6779 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
6780 break;
6781 case LOWORD(X509_CERT_POLICIES):
6782 decodeFunc = CRYPT_AsnDecodeCertPolicies;
6783 break;
6784 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
6785 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
6786 break;
6787 case LOWORD(PKCS_RSA_PRIVATE_KEY):
6788 decodeFunc = CRYPT_AsnDecodeRsaPrivKey;
6789 break;
6790 case LOWORD(X509_UNICODE_NAME):
6791 decodeFunc = CRYPT_AsnDecodeUnicodeName;
6792 break;
6793 case LOWORD(PKCS_ATTRIBUTE):
6794 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
6795 break;
6796 case LOWORD(X509_UNICODE_NAME_VALUE):
6797 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
6798 break;
6799 case LOWORD(X509_OCTET_STRING):
6800 decodeFunc = CRYPT_AsnDecodeOctetString;
6801 break;
6802 case LOWORD(X509_BITS):
6803 case LOWORD(X509_KEY_USAGE):
6804 decodeFunc = CRYPT_AsnDecodeBits;
6805 break;
6806 case LOWORD(X509_INTEGER):
6807 decodeFunc = CRYPT_AsnDecodeInt;
6808 break;
6809 case LOWORD(X509_MULTI_BYTE_INTEGER):
6810 decodeFunc = CRYPT_AsnDecodeInteger;
6811 break;
6812 case LOWORD(X509_MULTI_BYTE_UINT):
6813 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
6814 break;
6815 case LOWORD(X509_ENUMERATED):
6816 decodeFunc = CRYPT_AsnDecodeEnumerated;
6817 break;
6818 case LOWORD(X509_CHOICE_OF_TIME):
6819 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
6820 break;
6821 case LOWORD(X509_AUTHORITY_KEY_ID2):
6822 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
6823 break;
6824 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
6825 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
6826 break;
6827 case LOWORD(PKCS_CONTENT_INFO):
6828 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
6829 break;
6830 case LOWORD(X509_SEQUENCE_OF_ANY):
6831 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
6832 break;
6833 case LOWORD(PKCS_UTC_TIME):
6834 decodeFunc = CRYPT_AsnDecodeUtcTime;
6835 break;
6836 case LOWORD(X509_CRL_DIST_POINTS):
6837 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
6838 break;
6839 case LOWORD(X509_ENHANCED_KEY_USAGE):
6840 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
6841 break;
6842 case LOWORD(PKCS_CTL):
6843 decodeFunc = CRYPT_AsnDecodeCTL;
6844 break;
6845 case LOWORD(PKCS_SMIME_CAPABILITIES):
6846 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
6847 break;
6848 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
6849 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
6850 break;
6851 case LOWORD(PKCS_ATTRIBUTES):
6852 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
6853 break;
6854 case LOWORD(X509_ISSUING_DIST_POINT):
6855 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
6856 break;
6857 case LOWORD(X509_NAME_CONSTRAINTS):
6858 decodeFunc = CRYPT_AsnDecodeNameConstraints;
6859 break;
6860 case LOWORD(X509_POLICY_MAPPINGS):
6861 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6862 break;
6863 case LOWORD(X509_POLICY_CONSTRAINTS):
6864 decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
6865 break;
6866 case LOWORD(PKCS7_SIGNER_INFO):
6867 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
6868 break;
6869 case LOWORD(CMS_SIGNER_INFO):
6870 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
6871 break;
6872 case LOWORD(X509_OBJECT_IDENTIFIER):
6873 decodeFunc = CRYPT_AsnDecodeObjectIdentifier;
6874 break;
6875 case LOWORD(X509_ECC_SIGNATURE):
6876 decodeFunc = CRYPT_AsnDecodeEccSignature;
6877 break;
6878 case LOWORD(CNG_RSA_PUBLIC_KEY_BLOB):
6879 decodeFunc = CRYPT_AsnDecodeRsaPubKey_Bcrypt;
6880 break;
6881 case LOWORD(OCSP_RESPONSE):
6882 decodeFunc = CRYPT_AsnDecodeOCSPResponse;
6883 break;
6884 case LOWORD(OCSP_BASIC_SIGNED_RESPONSE):
6885 decodeFunc = CRYPT_AsnDecodeOCSPBasicSignedResponse;
6886 break;
6887 case LOWORD(OCSP_BASIC_RESPONSE):
6888 decodeFunc = CRYPT_AsnDecodeOCSPBasicResponse;
6889 break;
6890 default:
6891 break;
6894 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
6895 decodeFunc = CRYPT_AsnDecodeExtensions;
6896 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
6897 decodeFunc = CRYPT_AsnDecodeUtcTime;
6898 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
6899 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
6900 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
6901 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
6902 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
6903 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6904 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
6905 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
6906 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
6907 decodeFunc = CRYPT_AsnDecodeEnumerated;
6908 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
6909 decodeFunc = CRYPT_AsnDecodeBits;
6910 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
6911 decodeFunc = CRYPT_AsnDecodeOctetString;
6912 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
6913 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
6914 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
6915 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
6916 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
6917 decodeFunc = CRYPT_AsnDecodeAltName;
6918 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
6919 decodeFunc = CRYPT_AsnDecodeAltName;
6920 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
6921 decodeFunc = CRYPT_AsnDecodeAltName;
6922 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
6923 decodeFunc = CRYPT_AsnDecodeAltName;
6924 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
6925 decodeFunc = CRYPT_AsnDecodeAltName;
6926 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
6927 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
6928 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
6929 decodeFunc = CRYPT_AsnDecodeCertPolicies;
6930 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
6931 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6932 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
6933 decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
6934 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
6935 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
6936 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
6937 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
6938 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
6939 decodeFunc = CRYPT_AsnDecodeNameConstraints;
6940 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
6941 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
6942 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
6943 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
6944 else if (!strcmp(lpszStructType, szOID_CTL))
6945 decodeFunc = CRYPT_AsnDecodeCTL;
6946 else if (!strcmp(lpszStructType, szOID_ECC_PUBLIC_KEY))
6947 decodeFunc = CRYPT_AsnDecodeObjectIdentifier;
6948 return decodeFunc;
6951 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
6952 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
6954 static HCRYPTOIDFUNCSET set = NULL;
6955 CryptDecodeObjectFunc decodeFunc = NULL;
6957 if (!set)
6958 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
6959 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
6960 (void **)&decodeFunc, hFunc);
6961 return decodeFunc;
6964 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
6965 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
6967 static HCRYPTOIDFUNCSET set = NULL;
6968 CryptDecodeObjectExFunc decodeFunc = NULL;
6970 if (!set)
6971 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
6972 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
6973 (void **)&decodeFunc, hFunc);
6974 return decodeFunc;
6977 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
6978 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
6979 DWORD *pcbStructInfo)
6981 return CryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
6982 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
6985 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
6986 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6987 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6989 BOOL ret = FALSE;
6990 CryptDecodeObjectExFunc decodeFunc;
6991 HCRYPTOIDFUNCADDR hFunc = NULL;
6993 TRACE_(crypt)("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
6994 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
6995 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
6997 if (!pvStructInfo && !pcbStructInfo)
6999 SetLastError(ERROR_INVALID_PARAMETER);
7000 return FALSE;
7002 if (cbEncoded > MAX_ENCODED_LEN)
7004 FIXME_(crypt)("Returning CRYPT_E_ASN1_LARGE, cbEncoded %lu.\n", cbEncoded);
7005 SetLastError(CRYPT_E_ASN1_LARGE);
7006 return FALSE;
7009 SetLastError(NOERROR);
7010 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
7012 if (!pvStructInfo)
7014 SetLastError(ERROR_INVALID_PARAMETER);
7015 return FALSE;
7017 *(BYTE **)pvStructInfo = NULL;
7019 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
7020 if (!decodeFunc)
7022 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
7023 debugstr_a(lpszStructType));
7024 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
7025 &hFunc);
7026 if (!decodeFunc)
7028 if (IS_INTOID(lpszStructType))
7029 FIXME("Unimplemented decoder for lpszStructType OID %d\n", LOWORD(lpszStructType));
7030 else
7031 FIXME("Unsupported decoder for lpszStructType %s\n", lpszStructType);
7034 if (decodeFunc)
7035 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
7036 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
7037 else
7039 CryptDecodeObjectFunc pCryptDecodeObject =
7040 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
7042 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
7043 * directly, as that could cause an infinite loop.
7045 if (pCryptDecodeObject)
7047 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
7049 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
7050 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
7051 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
7052 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
7054 ret = pCryptDecodeObject(dwCertEncodingType,
7055 lpszStructType, pbEncoded, cbEncoded, dwFlags,
7056 *(BYTE **)pvStructInfo, pcbStructInfo);
7057 if (!ret)
7058 CRYPT_FreeSpace(pDecodePara, *(BYTE **)pvStructInfo);
7061 else
7062 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
7063 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
7066 if (hFunc)
7067 CryptFreeOIDFunctionAddress(hFunc, 0);
7068 TRACE_(crypt)("returning %d\n", ret);
7069 return ret;
7072 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
7074 BOOL ret;
7076 TRACE_(crypt)("(%p)\n", pPFX);
7078 /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
7079 * version integer of length 1 (3 encoded byes) and at least one other
7080 * datum (two encoded bytes), plus at least two bytes for the outer
7081 * sequence. Thus, even an empty PFX blob is at least 7 bytes in length.
7083 if (pPFX->cbData < 7)
7084 ret = FALSE;
7085 else if (pPFX->pbData[0] == ASN_SEQUENCE)
7087 DWORD len;
7089 if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
7091 BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
7093 /* Need at least three bytes for the integer version */
7094 if (pPFX->cbData < 1 + lenLen + 3)
7095 ret = FALSE;
7096 else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
7097 pPFX->pbData[1 + lenLen + 1] != 1 || /* Definite length */
7098 pPFX->pbData[1 + lenLen + 2] != 3) /* PFX version */
7099 ret = FALSE;
7102 else
7103 ret = FALSE;
7104 return ret;