wined3d: Pass a wined3d_device_context to wined3d_cs_emit_blt_sub_resource().
[wine/zf.git] / dlls / crypt32 / decode.c
blob5d195d42f7b8e202461edf9c1e41bf4868cb82ea
1 /*
2 * Copyright 2005-2009 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
33 #include <assert.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
38 #define NONAMELESSUNION
40 #include "windef.h"
41 #include "winbase.h"
42 #include "wincrypt.h"
43 #include "winnls.h"
44 #include "snmp.h"
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "crypt32_private.h"
49 /* This is a bit arbitrary, but to set some limit: */
50 #define MAX_ENCODED_LEN 0x02000000
52 #define ASN_FLAGS_MASK 0xe0
53 #define ASN_TYPE_MASK 0x1f
55 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
56 WINE_DECLARE_DEBUG_CHANNEL(crypt);
58 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
59 DWORD, DWORD, void *, DWORD *);
60 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
61 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
63 /* Internal decoders don't do memory allocation or exception handling, and
64 * they report how many bytes they decoded.
66 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
67 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
69 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
70 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
71 DWORD *pcbDecoded);
72 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
73 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
74 DWORD *pcbDecoded);
75 /* Assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set ahead of time.
77 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
78 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
79 /* Assumes algo->Parameters.pbData is set ahead of time. */
80 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
81 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
82 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
83 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
84 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
85 static BOOL CRYPT_AsnDecodeOctets(const BYTE *pbEncoded,
86 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
87 DWORD *pcbDecoded);
88 /* Doesn't check the tag, assumes the caller does so */
89 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
90 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
91 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
92 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
93 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
94 * member has been initialized, doesn't do exception handling, and doesn't do
95 * memory allocation. Also doesn't check tag, assumes the caller has checked
96 * it.
98 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
99 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
100 DWORD *pcbDecoded);
101 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
102 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
103 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
104 DWORD *pcbDecoded);
105 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
106 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
107 DWORD *pcbDecoded);
109 /* Gets the number of length bytes from the given (leading) length byte */
110 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
112 /* Helper function to get the encoded length of the data starting at pbEncoded,
113 * where pbEncoded[0] is the tag. If the data are too short to contain a
114 * length or if the length is too large for cbEncoded, sets an appropriate
115 * error code and returns FALSE. If the encoded length is unknown due to
116 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
118 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
119 DWORD *len)
121 BOOL ret;
123 if (cbEncoded <= 1)
125 SetLastError(CRYPT_E_ASN1_CORRUPT);
126 ret = FALSE;
128 else if (pbEncoded[1] <= 0x7f)
130 if (pbEncoded[1] + 1 > cbEncoded)
132 SetLastError(CRYPT_E_ASN1_EOD);
133 ret = FALSE;
135 else
137 *len = pbEncoded[1];
138 ret = TRUE;
141 else if (pbEncoded[1] == 0x80)
143 *len = CMSG_INDEFINITE_LENGTH;
144 ret = TRUE;
146 else
148 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
150 if (lenLen > sizeof(DWORD) + 1)
152 SetLastError(CRYPT_E_ASN1_LARGE);
153 ret = FALSE;
155 else if (lenLen + 2 > cbEncoded)
157 SetLastError(CRYPT_E_ASN1_CORRUPT);
158 ret = FALSE;
160 else
162 DWORD out = 0;
164 pbEncoded += 2;
165 while (--lenLen)
167 out <<= 8;
168 out |= *pbEncoded++;
170 if (out + lenLen + 1 > cbEncoded)
172 SetLastError(CRYPT_E_ASN1_EOD);
173 ret = FALSE;
175 else
177 *len = out;
178 ret = TRUE;
182 return ret;
185 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
186 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
188 BOOL ret;
190 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
191 *len == CMSG_INDEFINITE_LENGTH)
193 SetLastError(CRYPT_E_ASN1_CORRUPT);
194 ret = FALSE;
196 return ret;
199 /* Helper function to check *pcbStructInfo, set it to the required size, and
200 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
201 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
202 * pointer to the newly allocated memory.
204 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
205 const CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
206 DWORD bytesNeeded)
208 BOOL ret = TRUE;
210 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
212 if (pDecodePara && pDecodePara->pfnAlloc)
213 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
214 else
215 *(BYTE **)pvStructInfo = LocalAlloc(LPTR, bytesNeeded);
216 if (!*(BYTE **)pvStructInfo)
217 ret = FALSE;
218 else
219 *pcbStructInfo = bytesNeeded;
221 else if (*pcbStructInfo < bytesNeeded)
223 *pcbStructInfo = bytesNeeded;
224 SetLastError(ERROR_MORE_DATA);
225 ret = FALSE;
227 else
228 *pcbStructInfo = bytesNeeded;
229 return ret;
232 static void CRYPT_FreeSpace(const CRYPT_DECODE_PARA *pDecodePara, LPVOID pv)
234 if (pDecodePara && pDecodePara->pfnFree)
235 pDecodePara->pfnFree(pv);
236 else
237 LocalFree(pv);
240 /* Helper function to check *pcbStructInfo and set it to the required size.
241 * Assumes pvStructInfo is not NULL.
243 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
245 BOOL ret;
247 if (*pcbStructInfo < bytesNeeded)
249 *pcbStructInfo = bytesNeeded;
250 SetLastError(ERROR_MORE_DATA);
251 ret = FALSE;
253 else
255 *pcbStructInfo = bytesNeeded;
256 ret = TRUE;
258 return ret;
261 /* tag:
262 * The expected tag of the item. If tag is 0, decodeFunc is called
263 * regardless of the tag value seen.
264 * offset:
265 * A sequence is decoded into a struct. The offset member is the
266 * offset of this item within that struct.
267 * decodeFunc:
268 * The decoder function to use. If this is NULL, then the member isn't
269 * decoded, but minSize space is reserved for it.
270 * minSize:
271 * The minimum amount of space occupied after decoding. You must set this.
272 * optional:
273 * If true, and the tag doesn't match the expected tag for this item,
274 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
275 * filled with 0 for this member.
276 * hasPointer, pointerOffset:
277 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
278 * the offset within the struct of the data pointer (or to the
279 * first data pointer, if more than one exist).
280 * size:
281 * Used by CRYPT_AsnDecodeSequence, not for your use.
283 struct AsnDecodeSequenceItem
285 BYTE tag;
286 DWORD offset;
287 InternalDecodeFunc decodeFunc;
288 DWORD minSize;
289 BOOL optional;
290 BOOL hasPointer;
291 DWORD pointerOffset;
292 DWORD size;
295 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
296 #define MEMBERSIZE(s, member, nextmember) \
297 (offsetof(s, nextmember) - offsetof(s, member))
299 /* Decodes the items in a sequence, where the items are described in items,
300 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
301 * pvStructInfo. nextData is a pointer to the memory location at which the
302 * first decoded item with a dynamic pointer should point.
303 * Upon decoding, *cbDecoded is the total number of bytes decoded.
304 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
306 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
307 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
308 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
310 BOOL ret;
311 DWORD i, decoded = 0;
312 const BYTE *ptr = pbEncoded;
314 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
315 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
317 for (i = 0, ret = TRUE; ret && i < cItem; i++)
319 if (cbEncoded - (ptr - pbEncoded) != 0)
321 DWORD itemLen;
323 if ((ret = CRYPT_GetLengthIndefinite(ptr,
324 cbEncoded - (ptr - pbEncoded), &itemLen)))
326 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
328 if (ptr[0] == items[i].tag || !items[i].tag)
330 DWORD itemEncodedLen;
332 if (itemLen == CMSG_INDEFINITE_LENGTH)
333 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
334 else
335 itemEncodedLen = 1 + itemLenBytes + itemLen;
336 if (nextData && pvStructInfo && items[i].hasPointer)
338 TRACE("Setting next pointer to %p\n",
339 nextData);
340 *(BYTE **)((BYTE *)pvStructInfo +
341 items[i].pointerOffset) = nextData;
343 if (items[i].decodeFunc)
345 DWORD itemDecoded;
347 if (pvStructInfo)
348 TRACE("decoding item %d\n", i);
349 else
350 TRACE("sizing item %d\n", i);
351 ret = items[i].decodeFunc(ptr, itemEncodedLen,
352 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
353 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
354 : NULL, &items[i].size, &itemDecoded);
355 if (ret)
357 if (items[i].size < items[i].minSize)
358 items[i].size = items[i].minSize;
359 else if (items[i].size > items[i].minSize)
361 /* Account for alignment padding */
362 items[i].size = ALIGN_DWORD_PTR(items[i].size);
364 TRACE("item %d size: %d\n", i, items[i].size);
365 if (nextData && items[i].hasPointer &&
366 items[i].size > items[i].minSize)
367 nextData += items[i].size - items[i].minSize;
368 if (itemDecoded > itemEncodedLen)
370 WARN("decoded length %d exceeds encoded %d\n",
371 itemDecoded, itemEncodedLen);
372 SetLastError(CRYPT_E_ASN1_CORRUPT);
373 ret = FALSE;
375 else
377 ptr += itemDecoded;
378 decoded += itemDecoded;
379 TRACE("item %d: decoded %d bytes\n", i,
380 itemDecoded);
383 else if (items[i].optional &&
384 GetLastError() == CRYPT_E_ASN1_BADTAG)
386 TRACE("skipping optional item %d\n", i);
387 items[i].size = items[i].minSize;
388 SetLastError(NOERROR);
389 ret = TRUE;
391 else
392 TRACE("item %d failed: %08x\n", i,
393 GetLastError());
395 else if (itemLen == CMSG_INDEFINITE_LENGTH)
397 ERR("can't use indefinite length encoding without a decoder\n");
398 SetLastError(CRYPT_E_ASN1_CORRUPT);
399 ret = FALSE;
401 else
403 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
404 ptr += itemEncodedLen;
405 decoded += itemEncodedLen;
406 items[i].size = items[i].minSize;
409 else if (items[i].optional)
411 TRACE("skipping optional item %d\n", i);
412 items[i].size = items[i].minSize;
414 else
416 TRACE("item %d: tag %02x doesn't match expected %02x\n",
417 i, ptr[0], items[i].tag);
418 SetLastError(CRYPT_E_ASN1_BADTAG);
419 ret = FALSE;
423 else if (items[i].optional)
425 TRACE("missing optional item %d, skipping\n", i);
426 items[i].size = items[i].minSize;
428 else
430 TRACE("not enough bytes for item %d, failing\n", i);
431 SetLastError(CRYPT_E_ASN1_CORRUPT);
432 ret = FALSE;
435 if (cbDecoded)
436 *cbDecoded = decoded;
437 TRACE("returning %d\n", ret);
438 return ret;
441 /* This decodes an arbitrary sequence into a contiguous block of memory
442 * (basically, a struct.) Each element being decoded is described by a struct
443 * AsnDecodeSequenceItem, see above.
444 * startingPointer is an optional pointer to the first place where dynamic
445 * data will be stored. If you know the starting offset, you may pass it
446 * here. Otherwise, pass NULL, and one will be inferred from the items.
448 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
449 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
450 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
451 DWORD *pcbDecoded, void *startingPointer)
453 BOOL ret;
455 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
456 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
457 startingPointer);
459 if (!cbEncoded)
461 SetLastError(CRYPT_E_ASN1_EOD);
462 return FALSE;
464 if (pbEncoded[0] == ASN_SEQUENCE)
466 DWORD dataLen;
468 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
470 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
471 const BYTE *ptr = pbEncoded + 1 + lenBytes;
472 BOOL indefinite = FALSE;
474 cbEncoded -= 1 + lenBytes;
475 if (dataLen == CMSG_INDEFINITE_LENGTH)
477 dataLen = cbEncoded;
478 indefinite = TRUE;
479 lenBytes += 2;
481 else if (cbEncoded < dataLen)
483 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
484 cbEncoded);
485 SetLastError(CRYPT_E_ASN1_CORRUPT);
486 ret = FALSE;
488 if (ret)
490 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
491 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
492 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
494 if (cbDecoded > cbEncoded - 2)
496 /* Not enough space for 0 TLV */
497 SetLastError(CRYPT_E_ASN1_CORRUPT);
498 ret = FALSE;
500 else if (*(ptr + cbDecoded) != 0 ||
501 *(ptr + cbDecoded + 1) != 0)
503 TRACE("expected 0 TLV\n");
504 SetLastError(CRYPT_E_ASN1_CORRUPT);
505 ret = FALSE;
507 else
508 cbDecoded += 2;
511 if (ret && !indefinite && cbDecoded != dataLen)
513 TRACE("expected %d decoded, got %d, failing\n", dataLen,
514 cbDecoded);
515 SetLastError(CRYPT_E_ASN1_CORRUPT);
516 ret = FALSE;
518 if (ret)
520 DWORD i, bytesNeeded = 0, structSize = 0;
522 for (i = 0; i < cItem; i++)
524 if (items[i].size > items[i].minSize)
525 bytesNeeded += items[i].size - items[i].minSize;
526 structSize = max( structSize, items[i].offset + items[i].minSize );
528 bytesNeeded += structSize;
529 if (pcbDecoded)
530 *pcbDecoded = 1 + lenBytes + cbDecoded;
531 if (!pvStructInfo)
532 *pcbStructInfo = bytesNeeded;
533 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
534 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
536 BYTE *nextData;
538 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
539 pvStructInfo = *(BYTE **)pvStructInfo;
540 if (startingPointer)
541 nextData = startingPointer;
542 else
543 nextData = (BYTE *)pvStructInfo + structSize;
544 memset(pvStructInfo, 0, structSize);
545 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
546 ptr, dataLen, dwFlags, pvStructInfo, nextData,
547 &cbDecoded);
548 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
549 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
554 else
556 SetLastError(CRYPT_E_ASN1_BADTAG);
557 ret = FALSE;
559 TRACE("returning %d (%08x)\n", ret, GetLastError());
560 return ret;
563 /* tag:
564 * The expected tag of the entire encoded array (usually a variant
565 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
566 * regardless of the tag seen.
567 * countOffset:
568 * The offset within the outer structure at which the count exists.
569 * For example, a structure such as CRYPT_ATTRIBUTES has countOffset == 0,
570 * while CRYPT_ATTRIBUTE has countOffset ==
571 * offsetof(CRYPT_ATTRIBUTE, cValue).
572 * arrayOffset:
573 * The offset within the outer structure at which the array pointer exists.
574 * For example, CRYPT_ATTRIBUTES has arrayOffset ==
575 * offsetof(CRYPT_ATTRIBUTES, rgAttr).
576 * minArraySize:
577 * The minimum size of the decoded array. On WIN32, this is always 8:
578 * sizeof(DWORD) + sizeof(void *). On WIN64, it can be larger due to
579 * alignment.
580 * decodeFunc:
581 * used to decode each item in the array
582 * itemSize:
583 * is the minimum size of each decoded item
584 * hasPointer:
585 * indicates whether each item has a dynamic pointer
586 * pointerOffset:
587 * indicates the offset within itemSize at which the pointer exists
589 struct AsnArrayDescriptor
591 BYTE tag;
592 DWORD countOffset;
593 DWORD arrayOffset;
594 DWORD minArraySize;
595 InternalDecodeFunc decodeFunc;
596 DWORD itemSize;
597 BOOL hasPointer;
598 DWORD pointerOffset;
601 struct AsnArrayItemSize
603 DWORD encodedLen;
604 DWORD size;
607 /* Decodes an array of like types into a structure described by a struct
608 * AsnArrayDescriptor.
610 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
611 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
612 const CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
613 DWORD *pcbDecoded)
615 BOOL ret = TRUE;
617 TRACE("%p, %p, %d, %p, %d\n", arrayDesc, pbEncoded,
618 cbEncoded, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
620 if (!cbEncoded)
622 SetLastError(CRYPT_E_ASN1_EOD);
623 ret = FALSE;
625 else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
627 DWORD dataLen;
629 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
631 DWORD bytesNeeded = arrayDesc->minArraySize, cItems = 0, decoded;
632 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
633 /* There can be arbitrarily many items, but there is often only one.
635 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
637 decoded = 1 + lenBytes;
638 if (dataLen)
640 const BYTE *ptr;
641 BOOL doneDecoding = FALSE;
643 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
645 if (dataLen == CMSG_INDEFINITE_LENGTH)
647 if (ptr[0] == 0)
649 doneDecoding = TRUE;
650 if (ptr[1] != 0)
652 SetLastError(CRYPT_E_ASN1_CORRUPT);
653 ret = FALSE;
655 else
656 decoded += 2;
659 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
660 doneDecoding = TRUE;
661 if (!doneDecoding)
663 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
665 /* Each item decoded may not tolerate extraneous bytes,
666 * so get the length of the next element if known.
668 if ((ret = CRYPT_GetLengthIndefinite(ptr,
669 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
671 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
672 itemEncoded = cbEncoded - (ptr - pbEncoded);
673 else
674 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
675 itemDataLen;
677 if (ret)
678 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
679 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
680 &itemDecoded);
681 if (ret)
683 /* Ignore an item that failed to decode but the decoder doesn't want to fail the whole process */
684 if (!size)
686 ptr += itemEncoded;
687 continue;
690 cItems++;
691 if (itemSizes != &itemSize)
692 itemSizes = CryptMemRealloc(itemSizes,
693 cItems * sizeof(struct AsnArrayItemSize));
694 else if (cItems > 1)
696 itemSizes =
697 CryptMemAlloc(
698 cItems * sizeof(struct AsnArrayItemSize));
699 if (itemSizes)
700 *itemSizes = itemSize;
702 if (itemSizes)
704 decoded += itemDecoded;
705 itemSizes[cItems - 1].encodedLen = itemEncoded;
706 itemSizes[cItems - 1].size = size;
707 bytesNeeded += size;
708 ptr += itemEncoded;
710 else
711 ret = FALSE;
716 if (ret)
718 if (pcbDecoded)
719 *pcbDecoded = decoded;
720 if (!pvStructInfo)
721 *pcbStructInfo = bytesNeeded;
722 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
723 pvStructInfo, pcbStructInfo, bytesNeeded)))
725 DWORD i, *pcItems;
726 BYTE *nextData;
727 const BYTE *ptr;
728 void *rgItems;
730 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
731 pvStructInfo = *(void **)pvStructInfo;
732 pcItems = pvStructInfo;
733 *pcItems = cItems;
734 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
736 rgItems = (BYTE *)pvStructInfo +
737 arrayDesc->minArraySize;
738 *(void **)((BYTE *)pcItems -
739 arrayDesc->countOffset + arrayDesc->arrayOffset) =
740 rgItems;
742 else
743 rgItems = *(void **)((BYTE *)pcItems -
744 arrayDesc->countOffset + arrayDesc->arrayOffset);
745 nextData = (BYTE *)rgItems + cItems * arrayDesc->itemSize;
746 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
747 i < cItems && ptr - pbEncoded - 1 - lenBytes <
748 dataLen; i++)
750 DWORD itemDecoded;
752 if (arrayDesc->hasPointer)
753 *(BYTE **)((BYTE *)rgItems + i * arrayDesc->itemSize
754 + arrayDesc->pointerOffset) = nextData;
755 ret = arrayDesc->decodeFunc(ptr,
756 itemSizes[i].encodedLen,
757 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
758 (BYTE *)rgItems + i * arrayDesc->itemSize,
759 &itemSizes[i].size, &itemDecoded);
760 if (ret)
762 nextData += itemSizes[i].size - arrayDesc->itemSize;
763 ptr += itemDecoded;
766 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
767 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
770 if (itemSizes != &itemSize)
771 CryptMemFree(itemSizes);
774 else
776 SetLastError(CRYPT_E_ASN1_BADTAG);
777 ret = FALSE;
779 return ret;
782 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
783 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
784 * to CRYPT_E_ASN1_CORRUPT.
785 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
786 * set!
788 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
789 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
791 BOOL ret;
792 DWORD dataLen;
794 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
796 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
797 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
799 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
800 bytesNeeded += 1 + lenBytes + dataLen;
802 if (pcbDecoded)
803 *pcbDecoded = 1 + lenBytes + dataLen;
804 if (!pvStructInfo)
805 *pcbStructInfo = bytesNeeded;
806 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
808 CRYPT_DER_BLOB *blob;
810 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
811 pvStructInfo = *(BYTE **)pvStructInfo;
812 blob = pvStructInfo;
813 blob->cbData = 1 + lenBytes + dataLen;
814 if (blob->cbData)
816 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
817 blob->pbData = (BYTE *)pbEncoded;
818 else
820 assert(blob->pbData);
821 memcpy(blob->pbData, pbEncoded, blob->cbData);
824 else
826 SetLastError(CRYPT_E_ASN1_CORRUPT);
827 ret = FALSE;
831 return ret;
834 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
835 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
836 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
837 DWORD *pcbDecoded)
839 BOOL ret;
841 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
842 pvStructInfo, *pcbStructInfo, pcbDecoded);
844 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
845 * place.
847 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
848 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
849 pcbDecoded);
850 if (ret && pvStructInfo)
852 CRYPT_BIT_BLOB *blob = pvStructInfo;
854 if (blob->cbData)
856 DWORD i;
857 BYTE temp;
859 for (i = 0; i < blob->cbData / 2; i++)
861 temp = blob->pbData[i];
862 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
863 blob->pbData[blob->cbData - i - 1] = temp;
867 TRACE("returning %d (%08x)\n", ret, GetLastError());
868 return ret;
871 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
872 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
873 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
875 BOOL ret = TRUE;
877 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
878 pDecodePara, pvStructInfo, *pcbStructInfo);
880 __TRY
882 struct AsnDecodeSequenceItem items[] = {
883 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
884 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
885 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
886 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
887 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
888 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
889 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
890 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
891 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
892 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
895 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
896 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
897 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
898 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
899 pcbStructInfo, NULL, NULL);
901 __EXCEPT_PAGE_FAULT
903 SetLastError(STATUS_ACCESS_VIOLATION);
904 ret = FALSE;
906 __ENDTRY
908 TRACE("Returning %d (%08x)\n", ret, GetLastError());
909 return ret;
912 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
913 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
915 BOOL ret;
916 DWORD dataLen;
918 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
920 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
922 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
923 dwFlags, pvStructInfo, pcbStructInfo, NULL);
924 if (pcbDecoded)
925 *pcbDecoded = 1 + lenBytes + dataLen;
927 return ret;
930 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
931 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
933 BOOL ret;
935 struct AsnDecodeSequenceItem items[] = {
936 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
937 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
938 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
939 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
942 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
943 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
944 pcbDecoded, NULL);
945 return ret;
948 static BOOL CRYPT_AsnDecodeCertExtensionsInternal(const BYTE *pbEncoded,
949 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
950 DWORD *pcbDecoded)
952 BOOL ret = TRUE;
953 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
954 offsetof(CERT_INFO, cExtension), offsetof(CERT_INFO, rgExtension),
955 FINALMEMBERSIZE(CERT_INFO, cExtension),
956 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
957 offsetof(CERT_EXTENSION, pszObjId) };
959 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
960 pvStructInfo, *pcbStructInfo, pcbDecoded);
962 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
963 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
964 return ret;
967 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
968 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
969 DWORD *pcbDecoded)
971 BOOL ret;
972 DWORD dataLen;
974 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
976 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
978 ret = CRYPT_AsnDecodeCertExtensionsInternal(pbEncoded + 1 + lenBytes,
979 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
980 if (ret && pcbDecoded)
981 *pcbDecoded = 1 + lenBytes + dataLen;
983 return ret;
986 static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
987 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
988 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
990 BOOL ret = TRUE;
991 struct AsnDecodeSequenceItem items[] = {
992 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
993 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
994 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
995 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
996 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
997 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
998 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
999 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
1000 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1001 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1002 Issuer.pbData) },
1003 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
1004 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
1005 FALSE, 0 },
1006 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
1007 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1008 Subject.pbData) },
1009 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
1010 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
1011 FALSE, TRUE, offsetof(CERT_INFO,
1012 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
1013 { ASN_CONTEXT | 1, offsetof(CERT_INFO, IssuerUniqueId),
1014 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1015 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
1016 { ASN_CONTEXT | 2, offsetof(CERT_INFO, SubjectUniqueId),
1017 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1018 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
1019 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
1020 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(CERT_INFO, cExtension),
1021 TRUE, TRUE, offsetof(CERT_INFO, rgExtension), 0 },
1024 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1025 pDecodePara, pvStructInfo, *pcbStructInfo);
1027 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1028 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1029 NULL, NULL);
1030 if (ret && pvStructInfo)
1032 CERT_INFO *info;
1034 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1035 info = *(CERT_INFO **)pvStructInfo;
1036 else
1037 info = pvStructInfo;
1038 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1039 !info->Subject.cbData)
1041 SetLastError(CRYPT_E_ASN1_CORRUPT);
1042 /* Don't need to deallocate, because it should have failed on the
1043 * first pass (and no memory was allocated.)
1045 ret = FALSE;
1049 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1050 return ret;
1053 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1054 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1055 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1057 BOOL ret = FALSE;
1059 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1060 pDecodePara, pvStructInfo, *pcbStructInfo);
1062 __TRY
1064 DWORD size = 0;
1066 /* Unless told not to, first try to decode it as a signed cert. */
1067 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1069 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1071 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1072 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1073 &signedCert, &size);
1074 if (ret)
1076 size = 0;
1077 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1078 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1079 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1080 pvStructInfo, pcbStructInfo);
1081 LocalFree(signedCert);
1084 /* Failing that, try it as an unsigned cert */
1085 if (!ret)
1087 size = 0;
1088 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1089 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1090 pDecodePara, pvStructInfo, pcbStructInfo);
1093 __EXCEPT_PAGE_FAULT
1095 SetLastError(STATUS_ACCESS_VIOLATION);
1097 __ENDTRY
1099 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1100 return ret;
1103 static BOOL CRYPT_AsnDecodeCRLEntryExtensions(const BYTE *pbEncoded,
1104 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1105 DWORD *pcbDecoded)
1107 BOOL ret = TRUE;
1108 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1109 offsetof(CRL_ENTRY, cExtension), offsetof(CRL_ENTRY, rgExtension),
1110 FINALMEMBERSIZE(CRL_ENTRY, cExtension),
1111 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1112 offsetof(CERT_EXTENSION, pszObjId) };
1114 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1115 pvStructInfo, *pcbStructInfo, pcbDecoded);
1117 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1118 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1119 return ret;
1122 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1123 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1125 BOOL ret;
1126 struct AsnDecodeSequenceItem items[] = {
1127 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1128 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1129 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1130 { 0, offsetof(CRL_ENTRY, RevocationDate),
1131 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1132 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1133 CRYPT_AsnDecodeCRLEntryExtensions,
1134 FINALMEMBERSIZE(CRL_ENTRY, cExtension), TRUE, TRUE,
1135 offsetof(CRL_ENTRY, rgExtension), 0 },
1137 PCRL_ENTRY entry = pvStructInfo;
1139 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1140 *pcbStructInfo);
1142 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1143 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1144 entry ? entry->SerialNumber.pbData : NULL);
1145 if (ret && entry && !entry->SerialNumber.cbData)
1147 WARN("empty CRL entry serial number\n");
1148 SetLastError(CRYPT_E_ASN1_CORRUPT);
1149 ret = FALSE;
1151 return ret;
1154 /* Warning: assumes pvStructInfo points to the cCRLEntry member of a CRL_INFO
1155 * whose rgCRLEntry member has been set prior to calling.
1157 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1158 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1160 BOOL ret;
1161 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1162 offsetof(CRL_INFO, cCRLEntry), offsetof(CRL_INFO, rgCRLEntry),
1163 MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1164 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1165 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1167 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1168 pvStructInfo, *pcbStructInfo, pcbDecoded);
1170 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1171 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1172 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1173 return ret;
1176 static BOOL CRYPT_AsnDecodeCRLExtensionsInternal(const BYTE *pbEncoded,
1177 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1178 DWORD *pcbDecoded)
1180 BOOL ret = TRUE;
1181 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1182 offsetof(CRL_INFO, cExtension), offsetof(CRL_INFO, rgExtension),
1183 FINALMEMBERSIZE(CRL_INFO, cExtension),
1184 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1185 offsetof(CERT_EXTENSION, pszObjId) };
1187 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1188 pvStructInfo, *pcbStructInfo, pcbDecoded);
1190 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1191 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1192 return ret;
1195 static BOOL CRYPT_AsnDecodeCRLExtensions(const BYTE *pbEncoded,
1196 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1197 DWORD *pcbDecoded)
1199 BOOL ret;
1200 DWORD dataLen;
1202 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1204 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1206 ret = CRYPT_AsnDecodeCRLExtensionsInternal(pbEncoded + 1 + lenBytes,
1207 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
1208 if (ret && pcbDecoded)
1209 *pcbDecoded = 1 + lenBytes + dataLen;
1211 return ret;
1214 static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1215 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1216 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1218 struct AsnDecodeSequenceItem items[] = {
1219 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1220 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1221 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1222 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1223 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1224 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1225 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1226 Issuer.pbData) },
1227 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1228 sizeof(FILETIME), FALSE, FALSE, 0 },
1229 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1230 sizeof(FILETIME), TRUE, FALSE, 0 },
1231 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1232 CRYPT_AsnDecodeCRLEntries, MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1233 TRUE, TRUE, offsetof(CRL_INFO, rgCRLEntry), 0 },
1234 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1235 CRYPT_AsnDecodeCRLExtensions, FINALMEMBERSIZE(CRL_INFO, cExtension),
1236 TRUE, TRUE, offsetof(CRL_INFO, rgExtension), 0 },
1238 BOOL ret = TRUE;
1240 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1241 pDecodePara, pvStructInfo, *pcbStructInfo);
1243 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags,
1244 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1246 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1247 return ret;
1250 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1251 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1252 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1254 BOOL ret = FALSE;
1256 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1257 pDecodePara, pvStructInfo, *pcbStructInfo);
1259 __TRY
1261 DWORD size = 0;
1263 /* Unless told not to, first try to decode it as a signed crl. */
1264 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1266 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1268 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1269 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1270 &signedCrl, &size);
1271 if (ret)
1273 size = 0;
1274 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1275 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1276 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1277 pvStructInfo, pcbStructInfo);
1278 LocalFree(signedCrl);
1281 /* Failing that, try it as an unsigned crl */
1282 if (!ret)
1284 size = 0;
1285 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1286 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1287 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1290 __EXCEPT_PAGE_FAULT
1292 SetLastError(STATUS_ACCESS_VIOLATION);
1294 __ENDTRY
1296 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1297 return ret;
1300 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1301 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1303 BOOL ret = TRUE;
1304 DWORD dataLen;
1306 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1307 pvStructInfo, *pcbStructInfo);
1309 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1311 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1312 DWORD bytesNeeded = sizeof(LPSTR);
1314 if (dataLen)
1316 const BYTE *ptr;
1317 char str[32];
1319 snprintf(str, sizeof(str), "%d.%d",
1320 pbEncoded[1 + lenBytes] / 40,
1321 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1322 * 40);
1323 bytesNeeded += strlen(str) + 1;
1324 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1325 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1327 int val = 0;
1329 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1330 (*ptr & 0x80))
1332 val <<= 7;
1333 val |= *ptr & 0x7f;
1334 ptr++;
1336 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1337 (*ptr & 0x80))
1339 SetLastError(CRYPT_E_ASN1_CORRUPT);
1340 ret = FALSE;
1342 else
1344 val <<= 7;
1345 val |= *ptr++;
1346 snprintf(str, sizeof(str), ".%d", val);
1347 bytesNeeded += strlen(str);
1351 if (pcbDecoded)
1352 *pcbDecoded = 1 + lenBytes + dataLen;
1353 if (!pvStructInfo)
1354 *pcbStructInfo = bytesNeeded;
1355 else if (*pcbStructInfo < bytesNeeded)
1357 *pcbStructInfo = bytesNeeded;
1358 SetLastError(ERROR_MORE_DATA);
1359 ret = FALSE;
1361 else
1363 if (dataLen)
1365 const BYTE *ptr;
1366 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1368 *pszObjId = 0;
1369 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1370 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1371 40) * 40);
1372 pszObjId += strlen(pszObjId);
1373 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1374 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1376 int val = 0;
1378 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1379 (*ptr & 0x80))
1381 val <<= 7;
1382 val |= *ptr & 0x7f;
1383 ptr++;
1385 val <<= 7;
1386 val |= *ptr++;
1387 sprintf(pszObjId, ".%d", val);
1388 pszObjId += strlen(pszObjId);
1391 else
1392 *(LPSTR *)pvStructInfo = NULL;
1393 *pcbStructInfo = bytesNeeded;
1396 return ret;
1399 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1400 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1402 BOOL ret;
1404 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1405 pvStructInfo, *pcbStructInfo);
1407 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1408 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1409 pvStructInfo, pcbStructInfo, pcbDecoded);
1410 else
1412 SetLastError(CRYPT_E_ASN1_BADTAG);
1413 ret = FALSE;
1415 return ret;
1418 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1419 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1421 struct AsnDecodeSequenceItem items[] = {
1422 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1423 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1424 offsetof(CERT_EXTENSION, pszObjId), 0 },
1425 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1426 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1427 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1428 CRYPT_AsnDecodeOctets, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1429 offsetof(CERT_EXTENSION, Value.pbData) },
1431 BOOL ret = TRUE;
1432 PCERT_EXTENSION ext = pvStructInfo;
1434 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1435 *pcbStructInfo);
1437 if (ext)
1438 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1439 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1440 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1441 pcbDecoded, ext ? ext->pszObjId : NULL);
1442 if (ext)
1443 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1444 debugstr_a(ext->pszObjId));
1445 TRACE("returning %d (%08x)\n", ret, GetLastError());
1446 return ret;
1449 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1450 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1451 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1453 BOOL ret = TRUE;
1455 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1456 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
1458 __TRY
1460 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1461 offsetof(CERT_EXTENSIONS, cExtension),
1462 offsetof(CERT_EXTENSIONS, rgExtension),
1463 sizeof(CERT_EXTENSIONS),
1464 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1465 offsetof(CERT_EXTENSION, pszObjId) };
1466 CERT_EXTENSIONS *exts = pvStructInfo;
1468 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1469 exts->rgExtension = (CERT_EXTENSION *)(exts + 1);
1470 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1471 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1473 __EXCEPT_PAGE_FAULT
1475 SetLastError(STATUS_ACCESS_VIOLATION);
1476 ret = FALSE;
1478 __ENDTRY
1479 return ret;
1482 /* Warning: this assumes the address of value->Value.pbData is already set, in
1483 * order to avoid overwriting memory. (In some cases, it may change it, if it
1484 * doesn't copy anything to memory.) Be sure to set it correctly!
1486 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1487 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1488 DWORD *pcbDecoded)
1490 BOOL ret = TRUE;
1491 DWORD dataLen;
1492 CERT_NAME_VALUE *value = pvStructInfo;
1494 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1496 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1497 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1499 switch (pbEncoded[0])
1501 case ASN_OCTETSTRING:
1502 valueType = CERT_RDN_OCTET_STRING;
1503 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1504 bytesNeeded += dataLen;
1505 break;
1506 case ASN_NUMERICSTRING:
1507 valueType = CERT_RDN_NUMERIC_STRING;
1508 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1509 bytesNeeded += dataLen;
1510 break;
1511 case ASN_PRINTABLESTRING:
1512 valueType = CERT_RDN_PRINTABLE_STRING;
1513 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1514 bytesNeeded += dataLen;
1515 break;
1516 case ASN_IA5STRING:
1517 valueType = CERT_RDN_IA5_STRING;
1518 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1519 bytesNeeded += dataLen;
1520 break;
1521 case ASN_T61STRING:
1522 valueType = CERT_RDN_T61_STRING;
1523 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1524 bytesNeeded += dataLen;
1525 break;
1526 case ASN_VIDEOTEXSTRING:
1527 valueType = CERT_RDN_VIDEOTEX_STRING;
1528 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1529 bytesNeeded += dataLen;
1530 break;
1531 case ASN_GRAPHICSTRING:
1532 valueType = CERT_RDN_GRAPHIC_STRING;
1533 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1534 bytesNeeded += dataLen;
1535 break;
1536 case ASN_VISIBLESTRING:
1537 valueType = CERT_RDN_VISIBLE_STRING;
1538 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1539 bytesNeeded += dataLen;
1540 break;
1541 case ASN_GENERALSTRING:
1542 valueType = CERT_RDN_GENERAL_STRING;
1543 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1544 bytesNeeded += dataLen;
1545 break;
1546 case ASN_UNIVERSALSTRING:
1547 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1548 SetLastError(CRYPT_E_ASN1_BADTAG);
1549 return FALSE;
1550 case ASN_BMPSTRING:
1551 valueType = CERT_RDN_BMP_STRING;
1552 bytesNeeded += dataLen;
1553 break;
1554 case ASN_UTF8STRING:
1555 valueType = CERT_RDN_UTF8_STRING;
1556 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1557 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * sizeof(WCHAR);
1558 break;
1559 default:
1560 SetLastError(CRYPT_E_ASN1_BADTAG);
1561 return FALSE;
1564 if (pcbDecoded)
1565 *pcbDecoded = 1 + lenBytes + dataLen;
1566 if (!value)
1567 *pcbStructInfo = bytesNeeded;
1568 else if (*pcbStructInfo < bytesNeeded)
1570 *pcbStructInfo = bytesNeeded;
1571 SetLastError(ERROR_MORE_DATA);
1572 ret = FALSE;
1574 else
1576 *pcbStructInfo = bytesNeeded;
1577 value->dwValueType = valueType;
1578 if (dataLen)
1580 DWORD i;
1582 assert(value->Value.pbData);
1583 switch (pbEncoded[0])
1585 case ASN_OCTETSTRING:
1586 case ASN_NUMERICSTRING:
1587 case ASN_PRINTABLESTRING:
1588 case ASN_IA5STRING:
1589 case ASN_T61STRING:
1590 case ASN_VIDEOTEXSTRING:
1591 case ASN_GRAPHICSTRING:
1592 case ASN_VISIBLESTRING:
1593 case ASN_GENERALSTRING:
1594 value->Value.cbData = dataLen;
1595 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1596 memcpy(value->Value.pbData,
1597 pbEncoded + 1 + lenBytes, dataLen);
1598 else
1599 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1600 lenBytes;
1601 break;
1602 case ASN_BMPSTRING:
1604 LPWSTR str = (LPWSTR)value->Value.pbData;
1606 value->Value.cbData = dataLen;
1607 for (i = 0; i < dataLen / 2; i++)
1608 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1609 pbEncoded[1 + lenBytes + 2 * i + 1];
1610 break;
1612 case ASN_UTF8STRING:
1614 LPWSTR str = (LPWSTR)value->Value.pbData;
1616 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1617 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1618 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1619 break;
1623 else
1625 value->Value.cbData = 0;
1626 value->Value.pbData = NULL;
1630 return ret;
1633 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1634 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1635 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1637 BOOL ret = TRUE;
1639 __TRY
1641 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1642 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1643 if (ret && pvStructInfo)
1645 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1646 pcbStructInfo, *pcbStructInfo);
1647 if (ret)
1649 CERT_NAME_VALUE *value;
1651 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1652 pvStructInfo = *(BYTE **)pvStructInfo;
1653 value = pvStructInfo;
1654 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1655 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1656 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1657 pcbStructInfo, NULL);
1658 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1659 CRYPT_FreeSpace(pDecodePara, value);
1663 __EXCEPT_PAGE_FAULT
1665 SetLastError(STATUS_ACCESS_VIOLATION);
1666 ret = FALSE;
1668 __ENDTRY
1669 return ret;
1672 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1673 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1674 DWORD *pcbDecoded)
1676 BOOL ret = TRUE;
1677 DWORD dataLen;
1678 CERT_NAME_VALUE *value = pvStructInfo;
1680 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1682 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1683 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1685 switch (pbEncoded[0])
1687 case ASN_NUMERICSTRING:
1688 valueType = CERT_RDN_NUMERIC_STRING;
1689 if (dataLen)
1690 bytesNeeded += (dataLen + 1) * 2;
1691 break;
1692 case ASN_PRINTABLESTRING:
1693 valueType = CERT_RDN_PRINTABLE_STRING;
1694 if (dataLen)
1695 bytesNeeded += (dataLen + 1) * 2;
1696 break;
1697 case ASN_IA5STRING:
1698 valueType = CERT_RDN_IA5_STRING;
1699 if (dataLen)
1700 bytesNeeded += (dataLen + 1) * 2;
1701 break;
1702 case ASN_T61STRING:
1703 valueType = CERT_RDN_T61_STRING;
1704 if (dataLen)
1705 bytesNeeded += (dataLen + 1) * 2;
1706 break;
1707 case ASN_VIDEOTEXSTRING:
1708 valueType = CERT_RDN_VIDEOTEX_STRING;
1709 if (dataLen)
1710 bytesNeeded += (dataLen + 1) * 2;
1711 break;
1712 case ASN_GRAPHICSTRING:
1713 valueType = CERT_RDN_GRAPHIC_STRING;
1714 if (dataLen)
1715 bytesNeeded += (dataLen + 1) * 2;
1716 break;
1717 case ASN_VISIBLESTRING:
1718 valueType = CERT_RDN_VISIBLE_STRING;
1719 if (dataLen)
1720 bytesNeeded += (dataLen + 1) * 2;
1721 break;
1722 case ASN_GENERALSTRING:
1723 valueType = CERT_RDN_GENERAL_STRING;
1724 if (dataLen)
1725 bytesNeeded += (dataLen + 1) * 2;
1726 break;
1727 case ASN_UNIVERSALSTRING:
1728 valueType = CERT_RDN_UNIVERSAL_STRING;
1729 if (dataLen)
1730 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
1731 break;
1732 case ASN_BMPSTRING:
1733 valueType = CERT_RDN_BMP_STRING;
1734 if (dataLen)
1735 bytesNeeded += dataLen + sizeof(WCHAR);
1736 break;
1737 case ASN_UTF8STRING:
1738 valueType = CERT_RDN_UTF8_STRING;
1739 if (dataLen)
1740 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
1741 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
1742 break;
1743 default:
1744 SetLastError(CRYPT_E_ASN1_BADTAG);
1745 return FALSE;
1748 if (pcbDecoded)
1749 *pcbDecoded = 1 + lenBytes + dataLen;
1750 if (!value)
1751 *pcbStructInfo = bytesNeeded;
1752 else if (*pcbStructInfo < bytesNeeded)
1754 *pcbStructInfo = bytesNeeded;
1755 SetLastError(ERROR_MORE_DATA);
1756 ret = FALSE;
1758 else
1760 *pcbStructInfo = bytesNeeded;
1761 value->dwValueType = valueType;
1762 if (dataLen)
1764 DWORD i;
1765 LPWSTR str = (LPWSTR)value->Value.pbData;
1767 assert(value->Value.pbData);
1768 switch (pbEncoded[0])
1770 case ASN_NUMERICSTRING:
1771 case ASN_PRINTABLESTRING:
1772 case ASN_IA5STRING:
1773 case ASN_T61STRING:
1774 case ASN_VIDEOTEXSTRING:
1775 case ASN_GRAPHICSTRING:
1776 case ASN_VISIBLESTRING:
1777 case ASN_GENERALSTRING:
1778 value->Value.cbData = dataLen * 2;
1779 for (i = 0; i < dataLen; i++)
1780 str[i] = pbEncoded[1 + lenBytes + i];
1781 str[i] = 0;
1782 break;
1783 case ASN_UNIVERSALSTRING:
1784 value->Value.cbData = dataLen / 2;
1785 for (i = 0; i < dataLen / 4; i++)
1786 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1787 | pbEncoded[1 + lenBytes + 2 * i + 3];
1788 str[i] = 0;
1789 break;
1790 case ASN_BMPSTRING:
1791 value->Value.cbData = dataLen;
1792 for (i = 0; i < dataLen / 2; i++)
1793 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1794 pbEncoded[1 + lenBytes + 2 * i + 1];
1795 str[i] = 0;
1796 break;
1797 case ASN_UTF8STRING:
1798 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1799 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1800 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR);
1801 *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0;
1802 value->Value.cbData += sizeof(WCHAR);
1803 break;
1806 else
1808 value->Value.cbData = 0;
1809 value->Value.pbData = NULL;
1813 return ret;
1816 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1817 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1818 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1820 BOOL ret = TRUE;
1822 __TRY
1824 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1825 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1826 if (ret && pvStructInfo)
1828 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1829 pcbStructInfo, *pcbStructInfo);
1830 if (ret)
1832 CERT_NAME_VALUE *value;
1834 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1835 pvStructInfo = *(BYTE **)pvStructInfo;
1836 value = pvStructInfo;
1837 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1838 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1839 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1840 pcbStructInfo, NULL);
1841 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1842 CRYPT_FreeSpace(pDecodePara, value);
1846 __EXCEPT_PAGE_FAULT
1848 SetLastError(STATUS_ACCESS_VIOLATION);
1849 ret = FALSE;
1851 __ENDTRY
1852 return ret;
1855 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1856 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1858 BOOL ret;
1859 struct AsnDecodeSequenceItem items[] = {
1860 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1861 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1862 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1863 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1864 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1865 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1867 CERT_RDN_ATTR *attr = pvStructInfo;
1869 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1870 pvStructInfo, *pcbStructInfo);
1872 if (attr)
1873 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1874 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1875 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1876 attr ? attr->pszObjId : NULL);
1877 if (attr)
1879 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1880 debugstr_a(attr->pszObjId));
1881 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1883 TRACE("returning %d (%08x)\n", ret, GetLastError());
1884 return ret;
1887 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1888 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1890 BOOL ret = TRUE;
1891 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1892 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1893 sizeof(CERT_RDN),
1894 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1895 offsetof(CERT_RDN_ATTR, pszObjId) };
1897 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1898 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1899 return ret;
1902 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1903 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1904 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1906 BOOL ret = TRUE;
1908 __TRY
1910 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1911 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
1912 sizeof(CERT_NAME_INFO),
1913 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1914 offsetof(CERT_RDN, rgRDNAttr) };
1915 DWORD bytesNeeded = 0;
1917 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1918 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
1919 NULL);
1920 if (ret)
1922 if (!pvStructInfo)
1923 *pcbStructInfo = bytesNeeded;
1924 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1925 pvStructInfo, pcbStructInfo, bytesNeeded)))
1927 CERT_NAME_INFO *info;
1929 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1930 pvStructInfo = *(BYTE **)pvStructInfo;
1931 info = pvStructInfo;
1932 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
1933 sizeof(CERT_NAME_INFO));
1934 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1935 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1936 &bytesNeeded, NULL);
1937 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1938 CRYPT_FreeSpace(pDecodePara, info);
1942 __EXCEPT_PAGE_FAULT
1944 SetLastError(STATUS_ACCESS_VIOLATION);
1945 ret = FALSE;
1947 __ENDTRY
1948 return ret;
1951 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1952 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1953 DWORD *pcbDecoded)
1955 BOOL ret;
1956 struct AsnDecodeSequenceItem items[] = {
1957 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1958 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1959 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1960 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1961 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1962 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1964 CERT_RDN_ATTR *attr = pvStructInfo;
1966 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1967 pvStructInfo, *pcbStructInfo);
1969 if (attr)
1970 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1971 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1972 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1973 attr ? attr->pszObjId : NULL);
1974 if (attr)
1976 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1977 debugstr_a(attr->pszObjId));
1978 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1980 TRACE("returning %d (%08x)\n", ret, GetLastError());
1981 return ret;
1984 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1985 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1987 BOOL ret = TRUE;
1988 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1989 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1990 sizeof(CERT_RDN),
1991 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1992 offsetof(CERT_RDN_ATTR, pszObjId) };
1994 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1995 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1996 return ret;
1999 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
2000 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2001 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2003 BOOL ret = TRUE;
2005 __TRY
2007 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2008 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
2009 sizeof(CERT_NAME_INFO),
2010 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
2011 offsetof(CERT_RDN, rgRDNAttr) };
2012 DWORD bytesNeeded = 0;
2014 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2015 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
2016 NULL);
2017 if (ret)
2019 if (!pvStructInfo)
2020 *pcbStructInfo = bytesNeeded;
2021 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2022 pvStructInfo, pcbStructInfo, bytesNeeded)))
2024 CERT_NAME_INFO *info;
2026 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2027 pvStructInfo = *(BYTE **)pvStructInfo;
2028 info = pvStructInfo;
2029 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
2030 sizeof(CERT_NAME_INFO));
2031 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2032 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2033 &bytesNeeded, NULL);
2034 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2035 CRYPT_FreeSpace(pDecodePara, info);
2039 __EXCEPT_PAGE_FAULT
2041 SetLastError(STATUS_ACCESS_VIOLATION);
2042 ret = FALSE;
2044 __ENDTRY
2045 return ret;
2048 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
2049 DWORD *pcbDecoded)
2051 BOOL ret = TRUE, done = FALSE;
2052 DWORD indefiniteNestingLevels = 0, decoded = 0;
2054 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
2056 do {
2057 DWORD dataLen;
2059 if (!cbEncoded)
2060 done = TRUE;
2061 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
2062 &dataLen)))
2064 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2066 if (dataLen == CMSG_INDEFINITE_LENGTH)
2068 indefiniteNestingLevels++;
2069 pbEncoded += 1 + lenBytes;
2070 cbEncoded -= 1 + lenBytes;
2071 decoded += 1 + lenBytes;
2072 TRACE("indefiniteNestingLevels = %d\n",
2073 indefiniteNestingLevels);
2075 else
2077 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
2078 indefiniteNestingLevels)
2080 indefiniteNestingLevels--;
2081 TRACE("indefiniteNestingLevels = %d\n",
2082 indefiniteNestingLevels);
2084 pbEncoded += 1 + lenBytes + dataLen;
2085 cbEncoded -= 1 + lenBytes + dataLen;
2086 decoded += 1 + lenBytes + dataLen;
2087 if (!indefiniteNestingLevels)
2088 done = TRUE;
2091 } while (ret && !done);
2092 /* If we haven't found all 0 TLVs, we haven't found the end */
2093 if (ret && indefiniteNestingLevels)
2095 SetLastError(CRYPT_E_ASN1_EOD);
2096 ret = FALSE;
2098 if (ret)
2099 *pcbDecoded = decoded;
2100 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
2101 return ret;
2104 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
2105 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2106 DWORD *pcbDecoded)
2108 BOOL ret = TRUE;
2109 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
2111 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2112 pvStructInfo, *pcbStructInfo);
2114 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
2116 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2117 bytesNeeded += encodedLen;
2118 if (!pvStructInfo)
2119 *pcbStructInfo = bytesNeeded;
2120 else if (*pcbStructInfo < bytesNeeded)
2122 SetLastError(ERROR_MORE_DATA);
2123 *pcbStructInfo = bytesNeeded;
2124 ret = FALSE;
2126 else
2128 PCRYPT_OBJID_BLOB blob = pvStructInfo;
2130 *pcbStructInfo = bytesNeeded;
2131 blob->cbData = encodedLen;
2132 if (encodedLen)
2134 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2135 blob->pbData = (LPBYTE)pbEncoded;
2136 else
2138 assert(blob->pbData);
2139 memcpy(blob->pbData, pbEncoded, blob->cbData);
2142 else
2143 blob->pbData = NULL;
2145 if (pcbDecoded)
2146 *pcbDecoded = encodedLen;
2148 return ret;
2151 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2152 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2154 BOOL ret;
2155 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2156 offsetof(CTL_USAGE, cUsageIdentifier),
2157 offsetof(CTL_USAGE, rgpszUsageIdentifier),
2158 sizeof(CTL_USAGE),
2159 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2161 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2162 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2163 return ret;
2166 static BOOL CRYPT_AsnDecodeCTLEntryAttributes(const BYTE *pbEncoded,
2167 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2168 DWORD *pcbDecoded)
2170 struct AsnArrayDescriptor arrayDesc = { 0,
2171 offsetof(CTL_ENTRY, cAttribute), offsetof(CTL_ENTRY, rgAttribute),
2172 FINALMEMBERSIZE(CTL_ENTRY, cAttribute),
2173 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2174 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2175 BOOL ret;
2177 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2178 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2179 return ret;
2182 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2183 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2185 struct AsnDecodeSequenceItem items[] = {
2186 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2187 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2188 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2189 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2190 CRYPT_AsnDecodeCTLEntryAttributes,
2191 FINALMEMBERSIZE(CTL_ENTRY, cAttribute), FALSE, TRUE,
2192 offsetof(CTL_ENTRY, rgAttribute), 0 },
2194 BOOL ret = TRUE;
2195 CTL_ENTRY *entry = pvStructInfo;
2197 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2198 *pcbStructInfo);
2200 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2201 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2202 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2203 return ret;
2206 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2207 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2209 BOOL ret;
2210 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2211 offsetof(CTL_INFO, cCTLEntry), offsetof(CTL_INFO, rgCTLEntry),
2212 FINALMEMBERSIZE(CTL_INFO, cExtension),
2213 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2214 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2216 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2217 pvStructInfo, *pcbStructInfo, pcbDecoded);
2219 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2220 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2221 return ret;
2224 static BOOL CRYPT_AsnDecodeCTLExtensionsInternal(const BYTE *pbEncoded,
2225 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2226 DWORD *pcbDecoded)
2228 BOOL ret = TRUE;
2229 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2230 offsetof(CTL_INFO, cExtension), offsetof(CTL_INFO, rgExtension),
2231 FINALMEMBERSIZE(CTL_INFO, cExtension),
2232 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
2233 offsetof(CERT_EXTENSION, pszObjId) };
2235 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2236 pvStructInfo, *pcbStructInfo, pcbDecoded);
2238 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2239 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2240 return ret;
2243 static BOOL CRYPT_AsnDecodeCTLExtensions(const BYTE *pbEncoded,
2244 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2245 DWORD *pcbDecoded)
2247 BOOL ret;
2248 DWORD dataLen;
2250 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2252 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2254 ret = CRYPT_AsnDecodeCTLExtensionsInternal(pbEncoded + 1 + lenBytes,
2255 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2256 if (ret && pcbDecoded)
2257 *pcbDecoded = 1 + lenBytes + dataLen;
2259 return ret;
2262 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2263 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2264 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2266 BOOL ret = FALSE;
2268 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2269 pDecodePara, pvStructInfo, *pcbStructInfo);
2271 __TRY
2273 struct AsnDecodeSequenceItem items[] = {
2274 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2275 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2276 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2277 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2278 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2279 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2280 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), TRUE,
2281 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2282 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2283 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2284 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2285 { 0, offsetof(CTL_INFO, ThisUpdate),
2286 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2287 0 },
2288 { 0, offsetof(CTL_INFO, NextUpdate),
2289 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2290 0 },
2291 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2292 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2293 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2294 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2295 CRYPT_AsnDecodeCTLEntries,
2296 MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension),
2297 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2298 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2299 CRYPT_AsnDecodeCTLExtensions, FINALMEMBERSIZE(CTL_INFO, cExtension),
2300 TRUE, TRUE, offsetof(CTL_INFO, rgExtension), 0 },
2303 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2304 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2305 pcbStructInfo, NULL, NULL);
2307 __EXCEPT_PAGE_FAULT
2309 SetLastError(STATUS_ACCESS_VIOLATION);
2311 __ENDTRY
2312 return ret;
2315 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2316 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2317 DWORD *pcbDecoded)
2319 BOOL ret;
2320 struct AsnDecodeSequenceItem items[] = {
2321 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2322 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2323 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2324 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2325 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2326 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2328 PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
2330 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2331 pvStructInfo, *pcbStructInfo);
2333 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2334 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2335 pcbDecoded, capability ? capability->pszObjId : NULL);
2336 TRACE("returning %d\n", ret);
2337 return ret;
2340 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2341 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2342 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2344 BOOL ret = FALSE;
2346 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2347 pDecodePara, pvStructInfo, *pcbStructInfo);
2349 __TRY
2351 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2352 offsetof(CRYPT_SMIME_CAPABILITIES, cCapability),
2353 offsetof(CRYPT_SMIME_CAPABILITIES, rgCapability),
2354 sizeof(CRYPT_SMIME_CAPABILITIES),
2355 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2356 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2357 CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
2359 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2360 capabilities->rgCapability = (CRYPT_SMIME_CAPABILITY *)(capabilities + 1);
2361 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2362 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2364 __EXCEPT_PAGE_FAULT
2366 SetLastError(STATUS_ACCESS_VIOLATION);
2368 __ENDTRY
2369 TRACE("returning %d\n", ret);
2370 return ret;
2373 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
2374 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2375 DWORD *pcbDecoded)
2377 BOOL ret = TRUE;
2378 DWORD dataLen;
2379 LPSTR *pStr = pvStructInfo;
2381 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2383 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2384 DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
2386 if (pbEncoded[0] != ASN_IA5STRING)
2388 SetLastError(CRYPT_E_ASN1_CORRUPT);
2389 ret = FALSE;
2391 else
2393 bytesNeeded += dataLen;
2394 if (pcbDecoded)
2395 *pcbDecoded = 1 + lenBytes + dataLen;
2396 if (!pvStructInfo)
2397 *pcbStructInfo = bytesNeeded;
2398 else if (*pcbStructInfo < bytesNeeded)
2400 *pcbStructInfo = bytesNeeded;
2401 SetLastError(ERROR_MORE_DATA);
2402 ret = FALSE;
2404 else
2406 *pcbStructInfo = bytesNeeded;
2407 if (dataLen)
2409 LPSTR str = *pStr;
2411 assert(str);
2412 memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
2413 str[dataLen] = 0;
2415 else
2416 *pStr = NULL;
2420 return ret;
2423 static BOOL CRYPT_AsnDecodeNoticeNumbers(const BYTE *pbEncoded,
2424 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2425 DWORD *pcbDecoded)
2427 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2428 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2429 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, rgNoticeNumbers),
2430 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2431 CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
2432 BOOL ret;
2434 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2435 pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
2437 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2438 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2439 TRACE("returning %d\n", ret);
2440 return ret;
2443 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
2444 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2445 DWORD *pcbDecoded)
2447 BOOL ret;
2448 struct AsnDecodeSequenceItem items[] = {
2449 { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2450 pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
2451 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
2452 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2453 cNoticeNumbers), CRYPT_AsnDecodeNoticeNumbers,
2454 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2455 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2456 rgNoticeNumbers), 0 },
2458 DWORD bytesNeeded = 0;
2460 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2461 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2463 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2464 pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
2465 NULL);
2466 if (ret)
2468 /* The caller is expecting a pointer to a
2469 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
2470 * CRYPT_AsnDecodeSequence is decoding a
2471 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. Increment the bytes
2472 * needed, and decode again if the requisite space is available.
2474 bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
2475 if (!pvStructInfo)
2476 *pcbStructInfo = bytesNeeded;
2477 else if (*pcbStructInfo < bytesNeeded)
2479 *pcbStructInfo = bytesNeeded;
2480 SetLastError(ERROR_MORE_DATA);
2481 ret = FALSE;
2483 else
2485 PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
2487 *pcbStructInfo = bytesNeeded;
2488 /* The pointer (pvStructInfo) passed in points to the first dynamic
2489 * pointer, so use it as the pointer to the
2490 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
2491 * appropriate offset for the first dynamic pointer within the
2492 * notice reference by pointing to the first memory location past
2493 * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
2495 noticeRef =
2496 *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
2497 noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
2498 sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
2499 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags,
2500 NULL, noticeRef, &bytesNeeded, pcbDecoded, noticeRef->pszOrganization);
2503 TRACE("returning %d\n", ret);
2504 return ret;
2507 static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
2508 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2509 DWORD *pcbDecoded)
2511 BOOL ret = TRUE;
2512 DWORD dataLen;
2514 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2516 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2517 DWORD bytesNeeded = sizeof(LPWSTR);
2519 switch (pbEncoded[0])
2521 case ASN_NUMERICSTRING:
2522 if (dataLen)
2523 bytesNeeded += (dataLen + 1) * 2;
2524 break;
2525 case ASN_PRINTABLESTRING:
2526 if (dataLen)
2527 bytesNeeded += (dataLen + 1) * 2;
2528 break;
2529 case ASN_IA5STRING:
2530 if (dataLen)
2531 bytesNeeded += (dataLen + 1) * 2;
2532 break;
2533 case ASN_T61STRING:
2534 if (dataLen)
2535 bytesNeeded += (dataLen + 1) * 2;
2536 break;
2537 case ASN_VIDEOTEXSTRING:
2538 if (dataLen)
2539 bytesNeeded += (dataLen + 1) * 2;
2540 break;
2541 case ASN_GRAPHICSTRING:
2542 if (dataLen)
2543 bytesNeeded += (dataLen + 1) * 2;
2544 break;
2545 case ASN_VISIBLESTRING:
2546 if (dataLen)
2547 bytesNeeded += (dataLen + 1) * 2;
2548 break;
2549 case ASN_GENERALSTRING:
2550 if (dataLen)
2551 bytesNeeded += (dataLen + 1) * 2;
2552 break;
2553 case ASN_UNIVERSALSTRING:
2554 if (dataLen)
2555 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
2556 break;
2557 case ASN_BMPSTRING:
2558 if (dataLen)
2559 bytesNeeded += dataLen + sizeof(WCHAR);
2560 break;
2561 case ASN_UTF8STRING:
2562 if (dataLen)
2563 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
2564 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
2565 break;
2566 default:
2567 SetLastError(CRYPT_E_ASN1_BADTAG);
2568 return FALSE;
2571 if (pcbDecoded)
2572 *pcbDecoded = 1 + lenBytes + dataLen;
2573 if (!pvStructInfo)
2574 *pcbStructInfo = bytesNeeded;
2575 else if (*pcbStructInfo < bytesNeeded)
2577 *pcbStructInfo = bytesNeeded;
2578 SetLastError(ERROR_MORE_DATA);
2579 ret = FALSE;
2581 else
2583 LPWSTR *pStr = pvStructInfo;
2585 *pcbStructInfo = bytesNeeded;
2586 if (dataLen)
2588 DWORD i;
2589 LPWSTR str = *pStr;
2591 assert(str);
2592 switch (pbEncoded[0])
2594 case ASN_NUMERICSTRING:
2595 case ASN_PRINTABLESTRING:
2596 case ASN_IA5STRING:
2597 case ASN_T61STRING:
2598 case ASN_VIDEOTEXSTRING:
2599 case ASN_GRAPHICSTRING:
2600 case ASN_VISIBLESTRING:
2601 case ASN_GENERALSTRING:
2602 for (i = 0; i < dataLen; i++)
2603 str[i] = pbEncoded[1 + lenBytes + i];
2604 str[i] = 0;
2605 break;
2606 case ASN_UNIVERSALSTRING:
2607 for (i = 0; i < dataLen / 4; i++)
2608 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2609 | pbEncoded[1 + lenBytes + 2 * i + 3];
2610 str[i] = 0;
2611 break;
2612 case ASN_BMPSTRING:
2613 for (i = 0; i < dataLen / 2; i++)
2614 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2615 pbEncoded[1 + lenBytes + 2 * i + 1];
2616 str[i] = 0;
2617 break;
2618 case ASN_UTF8STRING:
2620 int len = MultiByteToWideChar(CP_UTF8, 0,
2621 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2622 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
2623 str[len] = 0;
2624 break;
2628 else
2629 *pStr = NULL;
2632 return ret;
2635 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2636 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2637 DWORD *pcbStructInfo, DWORD *pcbDecoded)
2639 BOOL ret;
2640 struct AsnDecodeSequenceItem items[] = {
2641 { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2642 pNoticeReference), CRYPT_AsnDecodeNoticeReference,
2643 sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
2644 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
2645 { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
2646 CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
2647 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
2649 PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
2651 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2652 pvStructInfo, *pcbStructInfo);
2654 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2655 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2656 pcbDecoded, notice ? notice->pNoticeReference : NULL);
2657 TRACE("returning %d\n", ret);
2658 return ret;
2661 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
2662 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2663 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2664 void *pvStructInfo, DWORD *pcbStructInfo)
2666 BOOL ret = FALSE;
2668 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2669 pDecodePara, pvStructInfo, *pcbStructInfo);
2671 __TRY
2673 DWORD bytesNeeded = 0;
2675 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
2676 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2677 NULL);
2678 if (ret)
2680 if (!pvStructInfo)
2681 *pcbStructInfo = bytesNeeded;
2682 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2683 pvStructInfo, pcbStructInfo, bytesNeeded)))
2685 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
2687 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2688 pvStructInfo = *(BYTE **)pvStructInfo;
2689 notice = pvStructInfo;
2690 notice->pNoticeReference =
2691 (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
2692 ((BYTE *)pvStructInfo +
2693 sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
2694 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2695 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
2696 pvStructInfo, &bytesNeeded, NULL);
2697 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2698 CRYPT_FreeSpace(pDecodePara, notice);
2702 __EXCEPT_PAGE_FAULT
2704 SetLastError(STATUS_ACCESS_VIOLATION);
2706 __ENDTRY
2707 TRACE("returning %d\n", ret);
2708 return ret;
2711 static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded,
2712 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2713 DWORD *pcbDecoded)
2715 BOOL ret;
2716 struct AsnArrayDescriptor arrayDesc = { 0,
2717 offsetof(CRYPT_ATTRIBUTE, cValue), offsetof(CRYPT_ATTRIBUTE, rgValue),
2718 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue),
2719 CRYPT_AsnDecodeCopyBytes,
2720 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2722 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2723 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
2725 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2726 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2727 return ret;
2730 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2731 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2732 DWORD *pcbDecoded)
2734 BOOL ret;
2735 struct AsnDecodeSequenceItem items[] = {
2736 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2737 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2738 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2739 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2740 CRYPT_AsnDecodePKCSAttributeValue,
2741 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE,
2742 TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2744 PCRYPT_ATTRIBUTE attr = pvStructInfo;
2746 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2747 pvStructInfo, *pcbStructInfo);
2749 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2750 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2751 pcbDecoded, attr ? attr->pszObjId : NULL);
2752 TRACE("returning %d\n", ret);
2753 return ret;
2756 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2757 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2758 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2760 BOOL ret = FALSE;
2762 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2763 pDecodePara, pvStructInfo, *pcbStructInfo);
2765 __TRY
2767 DWORD bytesNeeded = 0;
2769 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2770 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2771 if (ret)
2773 if (!pvStructInfo)
2774 *pcbStructInfo = bytesNeeded;
2775 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2776 pvStructInfo, pcbStructInfo, bytesNeeded)))
2778 PCRYPT_ATTRIBUTE attr;
2780 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2781 pvStructInfo = *(BYTE **)pvStructInfo;
2782 attr = pvStructInfo;
2783 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2784 sizeof(CRYPT_ATTRIBUTE));
2785 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2786 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2787 NULL);
2788 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2789 CRYPT_FreeSpace(pDecodePara, attr);
2793 __EXCEPT_PAGE_FAULT
2795 SetLastError(STATUS_ACCESS_VIOLATION);
2797 __ENDTRY
2798 TRACE("returning %d\n", ret);
2799 return ret;
2802 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2803 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2804 DWORD *pcbDecoded)
2806 struct AsnArrayDescriptor arrayDesc = { 0,
2807 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2808 sizeof(CRYPT_ATTRIBUTES),
2809 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2810 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2811 BOOL ret;
2813 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2814 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2815 return ret;
2818 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2819 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2820 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2822 BOOL ret = FALSE;
2824 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2825 pDecodePara, pvStructInfo, *pcbStructInfo);
2827 __TRY
2829 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
2830 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2831 sizeof(CRYPT_ATTRIBUTES),
2832 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE),
2833 TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2834 CRYPT_ATTRIBUTES *attrs = pvStructInfo;
2836 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2837 attrs->rgAttr = (CRYPT_ATTRIBUTE *)(attrs + 1);
2838 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2839 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2841 __EXCEPT_PAGE_FAULT
2843 SetLastError(STATUS_ACCESS_VIOLATION);
2845 __ENDTRY
2846 TRACE("returning %d\n", ret);
2847 return ret;
2850 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2851 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2853 CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
2854 BOOL ret = TRUE;
2855 struct AsnDecodeSequenceItem items[] = {
2856 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2857 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2858 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2859 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2860 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2861 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2864 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2865 pvStructInfo, *pcbStructInfo, pcbDecoded);
2867 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2868 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2869 pcbDecoded, algo ? algo->pszObjId : NULL);
2870 if (ret && pvStructInfo)
2872 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2873 debugstr_a(algo->pszObjId));
2875 return ret;
2878 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2879 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2880 DWORD *pcbDecoded)
2882 BOOL ret = TRUE;
2883 struct AsnDecodeSequenceItem items[] = {
2884 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2885 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2886 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2887 Algorithm.pszObjId) },
2888 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2889 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2890 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2892 PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
2894 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2895 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2896 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2897 return ret;
2900 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2901 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2902 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2904 BOOL ret = TRUE;
2906 __TRY
2908 DWORD bytesNeeded = 0;
2910 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2911 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2913 if (!pvStructInfo)
2914 *pcbStructInfo = bytesNeeded;
2915 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2916 pvStructInfo, pcbStructInfo, bytesNeeded)))
2918 PCERT_PUBLIC_KEY_INFO info;
2920 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2921 pvStructInfo = *(BYTE **)pvStructInfo;
2922 info = pvStructInfo;
2923 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2924 sizeof(CERT_PUBLIC_KEY_INFO);
2925 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2926 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2927 &bytesNeeded, NULL);
2928 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2929 CRYPT_FreeSpace(pDecodePara, info);
2933 __EXCEPT_PAGE_FAULT
2935 SetLastError(STATUS_ACCESS_VIOLATION);
2936 ret = FALSE;
2938 __ENDTRY
2939 return ret;
2942 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2943 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2945 BOOL ret;
2947 if (cbEncoded < 3)
2949 SetLastError(CRYPT_E_ASN1_CORRUPT);
2950 return FALSE;
2952 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2954 SetLastError(CRYPT_E_ASN1_CORRUPT);
2955 return FALSE;
2957 if (pbEncoded[1] > 1)
2959 SetLastError(CRYPT_E_ASN1_CORRUPT);
2960 return FALSE;
2962 if (pcbDecoded)
2963 *pcbDecoded = 3;
2964 if (!pvStructInfo)
2966 *pcbStructInfo = sizeof(BOOL);
2967 ret = TRUE;
2969 else if (*pcbStructInfo < sizeof(BOOL))
2971 *pcbStructInfo = sizeof(BOOL);
2972 SetLastError(ERROR_MORE_DATA);
2973 ret = FALSE;
2975 else
2977 *pcbStructInfo = sizeof(BOOL);
2978 *(BOOL *)pvStructInfo = pbEncoded[2] != 0;
2979 ret = TRUE;
2981 TRACE("returning %d (%08x)\n", ret, GetLastError());
2982 return ret;
2985 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2986 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2988 PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
2989 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2990 BOOL ret;
2992 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2993 pvStructInfo, *pcbStructInfo);
2995 if (cbEncoded < 2)
2997 SetLastError(CRYPT_E_ASN1_CORRUPT);
2998 return FALSE;
3000 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3001 if (1 + lenBytes > cbEncoded)
3003 SetLastError(CRYPT_E_ASN1_CORRUPT);
3004 return FALSE;
3006 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3008 switch (pbEncoded[0] & ASN_TYPE_MASK)
3010 case 1: /* rfc822Name */
3011 case 2: /* dNSName */
3012 case 6: /* uniformResourceIdentifier */
3013 if (memchr(pbEncoded + 1 + lenBytes, 0, dataLen))
3015 SetLastError(CRYPT_E_ASN1_RULE);
3016 ret = FALSE;
3018 else
3019 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
3020 break;
3021 case 4: /* directoryName */
3022 case 7: /* iPAddress */
3023 bytesNeeded += dataLen;
3024 break;
3025 case 8: /* registeredID */
3026 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
3027 &dataLen, NULL);
3028 if (ret)
3030 /* FIXME: ugly, shouldn't need to know internals of OID decode
3031 * function to use it.
3033 bytesNeeded += dataLen - sizeof(LPSTR);
3035 break;
3036 case 0: /* otherName */
3037 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
3038 SetLastError(CRYPT_E_ASN1_BADTAG);
3039 ret = FALSE;
3040 break;
3041 case 3: /* x400Address, unimplemented */
3042 case 5: /* ediPartyName, unimplemented */
3043 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
3044 SetLastError(CRYPT_E_ASN1_BADTAG);
3045 ret = FALSE;
3046 break;
3047 default:
3048 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
3049 SetLastError(CRYPT_E_ASN1_CORRUPT);
3050 ret = FALSE;
3052 if (ret)
3054 if (pcbDecoded)
3055 *pcbDecoded = 1 + lenBytes + dataLen;
3056 if (!entry)
3057 *pcbStructInfo = bytesNeeded;
3058 else if (*pcbStructInfo < bytesNeeded)
3060 *pcbStructInfo = bytesNeeded;
3061 SetLastError(ERROR_MORE_DATA);
3062 ret = FALSE;
3064 else
3066 *pcbStructInfo = bytesNeeded;
3067 /* MS used values one greater than the asn1 ones.. sigh */
3068 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
3069 switch (pbEncoded[0] & ASN_TYPE_MASK)
3071 case 1: /* rfc822Name */
3072 case 2: /* dNSName */
3073 case 6: /* uniformResourceIdentifier */
3075 DWORD i;
3077 for (i = 0; i < dataLen; i++)
3078 entry->u.pwszURL[i] =
3079 (WCHAR)pbEncoded[1 + lenBytes + i];
3080 entry->u.pwszURL[i] = 0;
3081 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
3082 debugstr_w(entry->u.pwszURL));
3083 break;
3085 case 4: /* directoryName */
3086 /* The data are memory-equivalent with the IPAddress case,
3087 * fall-through
3089 case 7: /* iPAddress */
3090 /* The next data pointer is in the pwszURL spot, that is,
3091 * the first 4 bytes. Need to move it to the next spot.
3093 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
3094 entry->u.IPAddress.cbData = dataLen;
3095 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
3096 dataLen);
3097 break;
3098 case 8: /* registeredID */
3099 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
3100 &entry->u.pszRegisteredID, &dataLen, NULL);
3101 break;
3106 return ret;
3109 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
3110 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3111 DWORD *pcbDecoded)
3113 BOOL ret;
3114 struct AsnArrayDescriptor arrayDesc = { 0,
3115 offsetof(CERT_ALT_NAME_INFO, cAltEntry),
3116 offsetof(CERT_ALT_NAME_INFO, rgAltEntry),
3117 sizeof(CERT_ALT_NAME_INFO),
3118 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3119 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3121 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3122 pvStructInfo, *pcbStructInfo, pcbDecoded);
3124 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3125 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3126 return ret;
3129 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
3130 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3131 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3133 BOOL ret;
3135 __TRY
3137 struct AsnDecodeSequenceItem items[] = {
3138 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
3139 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB),
3140 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
3141 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3142 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
3143 CRYPT_AsnDecodeOctets, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
3144 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
3145 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
3146 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3147 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3148 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
3151 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3152 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3153 pcbStructInfo, NULL, NULL);
3155 __EXCEPT_PAGE_FAULT
3157 SetLastError(STATUS_ACCESS_VIOLATION);
3158 ret = FALSE;
3160 __ENDTRY
3161 return ret;
3164 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
3165 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3166 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3168 BOOL ret;
3170 __TRY
3172 struct AsnDecodeSequenceItem items[] = {
3173 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
3174 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB),
3175 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
3176 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3177 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
3178 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
3179 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3180 AuthorityCertIssuer.rgAltEntry), 0 },
3181 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3182 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3183 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3184 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3185 AuthorityCertSerialNumber.pbData), 0 },
3188 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3189 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3190 pcbStructInfo, NULL, NULL);
3192 __EXCEPT_PAGE_FAULT
3194 SetLastError(STATUS_ACCESS_VIOLATION);
3195 ret = FALSE;
3197 __ENDTRY
3198 return ret;
3201 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
3202 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3203 DWORD *pcbDecoded)
3205 struct AsnDecodeSequenceItem items[] = {
3206 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
3207 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3208 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
3209 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
3210 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
3211 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
3213 CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
3215 return CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3216 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3217 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
3220 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
3221 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3222 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3224 BOOL ret;
3226 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3227 pDecodePara, pvStructInfo, *pcbStructInfo);
3229 __TRY
3231 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3232 offsetof(CERT_AUTHORITY_INFO_ACCESS, cAccDescr),
3233 offsetof(CERT_AUTHORITY_INFO_ACCESS, rgAccDescr),
3234 sizeof(CERT_AUTHORITY_INFO_ACCESS),
3235 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
3236 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
3237 CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
3239 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3240 info->rgAccDescr = (CERT_ACCESS_DESCRIPTION *)(info + 1);
3241 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3242 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3244 __EXCEPT_PAGE_FAULT
3246 SetLastError(STATUS_ACCESS_VIOLATION);
3247 ret = FALSE;
3249 __ENDTRY
3250 return ret;
3253 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
3254 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3256 BOOL ret;
3257 DWORD dataLen;
3259 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3260 pvStructInfo, *pcbStructInfo, pcbDecoded);
3262 /* The caller has already checked the tag, no need to check it again.
3263 * Check the outer length is valid:
3265 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
3267 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3268 DWORD innerLen;
3270 pbEncoded += 1 + lenBytes;
3271 cbEncoded -= 1 + lenBytes;
3272 if (dataLen == CMSG_INDEFINITE_LENGTH)
3273 cbEncoded -= 2; /* space for 0 TLV */
3274 /* Check the inner length is valid: */
3275 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
3277 DWORD decodedLen;
3279 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
3280 pvStructInfo, pcbStructInfo, &decodedLen);
3281 if (dataLen == CMSG_INDEFINITE_LENGTH)
3283 if (*(pbEncoded + decodedLen) != 0 ||
3284 *(pbEncoded + decodedLen + 1) != 0)
3286 TRACE("expected 0 TLV, got {%02x,%02x}\n",
3287 *(pbEncoded + decodedLen),
3288 *(pbEncoded + decodedLen + 1));
3289 SetLastError(CRYPT_E_ASN1_CORRUPT);
3290 ret = FALSE;
3292 else
3293 decodedLen += 2;
3295 if (ret && pcbDecoded)
3297 *pcbDecoded = 1 + lenBytes + decodedLen;
3298 TRACE("decoded %d bytes\n", *pcbDecoded);
3302 return ret;
3305 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
3306 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3307 DWORD *pcbDecoded)
3309 CRYPT_CONTENT_INFO *info = pvStructInfo;
3310 struct AsnDecodeSequenceItem items[] = {
3311 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
3312 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3313 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
3314 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
3315 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
3316 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
3317 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
3319 BOOL ret;
3321 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3322 pvStructInfo, *pcbStructInfo, pcbDecoded);
3324 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3325 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3326 pcbDecoded, info ? info->pszObjId : NULL);
3327 return ret;
3330 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
3331 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3332 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3334 BOOL ret = FALSE;
3336 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3337 pDecodePara, pvStructInfo, *pcbStructInfo);
3339 __TRY
3341 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
3342 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3343 if (ret && pvStructInfo)
3345 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3346 pcbStructInfo, *pcbStructInfo);
3347 if (ret)
3349 CRYPT_CONTENT_INFO *info;
3351 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3352 pvStructInfo = *(BYTE **)pvStructInfo;
3353 info = pvStructInfo;
3354 info->pszObjId = (LPSTR)((BYTE *)info +
3355 sizeof(CRYPT_CONTENT_INFO));
3356 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
3357 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3358 pcbStructInfo, NULL);
3359 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3360 CRYPT_FreeSpace(pDecodePara, info);
3364 __EXCEPT_PAGE_FAULT
3366 SetLastError(STATUS_ACCESS_VIOLATION);
3368 __ENDTRY
3369 return ret;
3372 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
3373 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3374 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
3376 BOOL ret;
3377 struct AsnDecodeSequenceItem items[] = {
3378 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
3379 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3380 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
3381 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3382 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
3383 0 },
3384 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
3385 CRYPT_AsnDecodePKCSContentInfoInternal,
3386 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
3387 ContentInfo.pszObjId), 0 },
3388 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
3389 CRYPT_AsnDecodeOctets, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
3390 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
3393 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3394 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
3395 NULL, NULL);
3396 return ret;
3399 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
3400 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3401 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3403 BOOL ret = TRUE;
3405 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3406 pDecodePara, pvStructInfo, *pcbStructInfo);
3408 __TRY
3410 DWORD bytesNeeded = 0;
3412 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3413 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3415 if (!pvStructInfo)
3416 *pcbStructInfo = bytesNeeded;
3417 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3418 pvStructInfo, pcbStructInfo, bytesNeeded)))
3420 CERT_ALT_NAME_INFO *name;
3422 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3423 pvStructInfo = *(BYTE **)pvStructInfo;
3424 name = pvStructInfo;
3425 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
3426 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
3427 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3428 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3429 &bytesNeeded, NULL);
3430 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3431 CRYPT_FreeSpace(pDecodePara, name);
3435 __EXCEPT_PAGE_FAULT
3437 SetLastError(STATUS_ACCESS_VIOLATION);
3438 ret = FALSE;
3440 __ENDTRY
3441 return ret;
3444 struct PATH_LEN_CONSTRAINT
3446 BOOL fPathLenConstraint;
3447 DWORD dwPathLenConstraint;
3450 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3451 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3452 DWORD *pcbDecoded)
3454 BOOL ret = TRUE;
3455 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3457 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3458 pvStructInfo, *pcbStructInfo, pcbDecoded);
3460 if (!pvStructInfo)
3462 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3463 &size, pcbDecoded);
3464 *pcbStructInfo = bytesNeeded;
3466 else if (*pcbStructInfo < bytesNeeded)
3468 SetLastError(ERROR_MORE_DATA);
3469 *pcbStructInfo = bytesNeeded;
3470 ret = FALSE;
3472 else
3474 struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
3476 *pcbStructInfo = bytesNeeded;
3477 size = sizeof(constraint->dwPathLenConstraint);
3478 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3479 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3480 if (ret)
3481 constraint->fPathLenConstraint = TRUE;
3482 TRACE("got an int, dwPathLenConstraint is %d\n",
3483 constraint->dwPathLenConstraint);
3485 TRACE("returning %d (%08x)\n", ret, GetLastError());
3486 return ret;
3489 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3490 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3491 DWORD *pcbDecoded)
3493 BOOL ret;
3494 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3495 offsetof(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3496 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint),
3497 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3498 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3499 offsetof(CERT_NAME_BLOB, pbData) };
3501 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3502 pvStructInfo, *pcbStructInfo, pcbDecoded);
3504 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3505 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3506 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3507 return ret;
3510 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3511 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3512 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3514 BOOL ret;
3516 __TRY
3518 struct AsnDecodeSequenceItem items[] = {
3519 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3520 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3521 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3522 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3523 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3524 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3525 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3526 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3527 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3528 TRUE, TRUE,
3529 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3532 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3533 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3534 pcbStructInfo, NULL, NULL);
3536 __EXCEPT_PAGE_FAULT
3538 SetLastError(STATUS_ACCESS_VIOLATION);
3539 ret = FALSE;
3541 __ENDTRY
3542 return ret;
3545 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3546 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3547 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3549 BOOL ret;
3551 __TRY
3553 struct AsnDecodeSequenceItem items[] = {
3554 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3555 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3556 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3557 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3558 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3561 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3562 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3563 pcbStructInfo, NULL, NULL);
3565 __EXCEPT_PAGE_FAULT
3567 SetLastError(STATUS_ACCESS_VIOLATION);
3568 ret = FALSE;
3570 __ENDTRY
3571 return ret;
3574 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
3575 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3576 DWORD *pcbDecoded)
3578 struct AsnDecodeSequenceItem items[] = {
3579 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
3580 pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3581 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
3582 0 },
3583 { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
3584 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3585 offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
3587 BOOL ret;
3588 CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
3590 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3591 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3593 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3594 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3595 pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
3596 return ret;
3599 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
3600 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3601 DWORD *pcbDecoded)
3603 BOOL ret;
3604 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3605 offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3606 offsetof(CERT_POLICY_INFO, rgPolicyQualifier),
3607 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier),
3608 CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
3609 offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
3611 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3612 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3614 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3615 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3616 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3617 return ret;
3620 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
3621 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3623 struct AsnDecodeSequenceItem items[] = {
3624 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
3625 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3626 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
3627 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3628 CRYPT_AsnDecodePolicyQualifiers,
3629 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier), TRUE,
3630 TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
3632 CERT_POLICY_INFO *info = pvStructInfo;
3633 BOOL ret;
3635 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3636 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3638 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3639 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3640 pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
3641 return ret;
3644 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
3645 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3646 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3648 BOOL ret = FALSE;
3650 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3651 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3653 __TRY
3655 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3656 offsetof(CERT_POLICIES_INFO, cPolicyInfo),
3657 offsetof(CERT_POLICIES_INFO, rgPolicyInfo),
3658 sizeof(CERT_POLICIES_INFO),
3659 CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
3660 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
3661 CERT_POLICIES_INFO *info = pvStructInfo;
3663 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3664 info->rgPolicyInfo = (CERT_POLICY_INFO *)(info + 1);
3666 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3667 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3669 __EXCEPT_PAGE_FAULT
3671 SetLastError(STATUS_ACCESS_VIOLATION);
3673 __ENDTRY
3674 return ret;
3677 static BOOL CRYPT_AsnDecodeCertPolicyMapping(const BYTE *pbEncoded,
3678 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3679 DWORD *pcbDecoded)
3681 struct AsnDecodeSequenceItem items[] = {
3682 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
3683 pszIssuerDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3684 FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy), 0 },
3685 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
3686 pszSubjectDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3687 FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszSubjectDomainPolicy), 0 },
3689 CERT_POLICY_MAPPING *mapping = pvStructInfo;
3690 BOOL ret;
3692 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3693 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3695 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3696 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3697 pcbDecoded, mapping ? mapping->pszIssuerDomainPolicy : NULL);
3698 return ret;
3701 static BOOL WINAPI CRYPT_AsnDecodeCertPolicyMappings(DWORD dwCertEncodingType,
3702 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3703 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3705 BOOL ret = FALSE;
3707 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3708 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3710 __TRY
3712 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3713 offsetof(CERT_POLICY_MAPPINGS_INFO, cPolicyMapping),
3714 offsetof(CERT_POLICY_MAPPINGS_INFO, rgPolicyMapping),
3715 sizeof(CERT_POLICY_MAPPING),
3716 CRYPT_AsnDecodeCertPolicyMapping, sizeof(CERT_POLICY_MAPPING), TRUE,
3717 offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy) };
3718 CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
3720 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3721 info->rgPolicyMapping = (CERT_POLICY_MAPPING *)(info + 1);
3722 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3723 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3725 __EXCEPT_PAGE_FAULT
3727 SetLastError(STATUS_ACCESS_VIOLATION);
3729 __ENDTRY
3730 return ret;
3733 static BOOL CRYPT_AsnDecodeRequireExplicit(const BYTE *pbEncoded,
3734 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3735 DWORD *pcbDecoded)
3737 BOOL ret;
3738 DWORD skip, size = sizeof(skip);
3740 if (!cbEncoded)
3742 SetLastError(CRYPT_E_ASN1_EOD);
3743 return FALSE;
3745 if (pbEncoded[0] != (ASN_CONTEXT | 0))
3747 SetLastError(CRYPT_E_ASN1_BADTAG);
3748 return FALSE;
3750 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3751 &skip, &size, pcbDecoded)))
3753 DWORD bytesNeeded = MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
3754 fRequireExplicitPolicy, fInhibitPolicyMapping);
3756 if (!pvStructInfo)
3757 *pcbStructInfo = bytesNeeded;
3758 else if (*pcbStructInfo < bytesNeeded)
3760 *pcbStructInfo = bytesNeeded;
3761 SetLastError(ERROR_MORE_DATA);
3762 ret = FALSE;
3764 else
3766 CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo,
3767 CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy);
3769 *pcbStructInfo = bytesNeeded;
3770 /* The BOOL is implicit: if the integer is present, then it's
3771 * TRUE.
3773 info->fRequireExplicitPolicy = TRUE;
3774 info->dwRequireExplicitPolicySkipCerts = skip;
3777 return ret;
3780 static BOOL CRYPT_AsnDecodeInhibitMapping(const BYTE *pbEncoded,
3781 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3782 DWORD *pcbDecoded)
3784 BOOL ret;
3785 DWORD skip, size = sizeof(skip);
3787 if (!cbEncoded)
3789 SetLastError(CRYPT_E_ASN1_EOD);
3790 return FALSE;
3792 if (pbEncoded[0] != (ASN_CONTEXT | 1))
3794 SetLastError(CRYPT_E_ASN1_BADTAG);
3795 return FALSE;
3797 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3798 &skip, &size, pcbDecoded)))
3800 DWORD bytesNeeded = FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
3801 fInhibitPolicyMapping);
3803 if (!pvStructInfo)
3804 *pcbStructInfo = bytesNeeded;
3805 else if (*pcbStructInfo < bytesNeeded)
3807 *pcbStructInfo = bytesNeeded;
3808 SetLastError(ERROR_MORE_DATA);
3809 ret = FALSE;
3811 else
3813 CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo,
3814 CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping);
3816 *pcbStructInfo = bytesNeeded;
3817 /* The BOOL is implicit: if the integer is present, then it's
3818 * TRUE.
3820 info->fInhibitPolicyMapping = TRUE;
3821 info->dwInhibitPolicyMappingSkipCerts = skip;
3824 return ret;
3827 static BOOL WINAPI CRYPT_AsnDecodeCertPolicyConstraints(
3828 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3829 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3830 void *pvStructInfo, DWORD *pcbStructInfo)
3832 BOOL ret = FALSE;
3834 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3835 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3837 __TRY
3839 struct AsnDecodeSequenceItem items[] = {
3840 { ASN_CONTEXT | 0,
3841 offsetof(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy),
3842 CRYPT_AsnDecodeRequireExplicit,
3843 MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy,
3844 fInhibitPolicyMapping), TRUE, FALSE, 0, 0 },
3845 { ASN_CONTEXT | 1,
3846 offsetof(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
3847 CRYPT_AsnDecodeInhibitMapping,
3848 FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
3849 TRUE, FALSE, 0, 0 },
3852 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3853 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3854 pcbStructInfo, NULL, NULL);
3856 __EXCEPT_PAGE_FAULT
3858 SetLastError(STATUS_ACCESS_VIOLATION);
3860 __ENDTRY
3861 return ret;
3864 #define RSA1_MAGIC 0x31415352
3866 struct DECODED_RSA_PUB_KEY
3868 DWORD pubexp;
3869 CRYPT_INTEGER_BLOB modulus;
3872 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3873 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3874 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3876 BOOL ret;
3878 __TRY
3880 struct AsnDecodeSequenceItem items[] = {
3881 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3882 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3883 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3884 0 },
3885 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3886 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3888 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3889 DWORD size = 0;
3891 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3892 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3893 &size, NULL, NULL);
3894 if (ret)
3896 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3897 decodedKey->modulus.cbData;
3899 if (!pvStructInfo)
3901 *pcbStructInfo = bytesNeeded;
3902 ret = TRUE;
3904 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3905 pvStructInfo, pcbStructInfo, bytesNeeded)))
3907 BLOBHEADER *hdr;
3908 RSAPUBKEY *rsaPubKey;
3910 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3911 pvStructInfo = *(BYTE **)pvStructInfo;
3912 hdr = pvStructInfo;
3913 hdr->bType = PUBLICKEYBLOB;
3914 hdr->bVersion = CUR_BLOB_VERSION;
3915 hdr->reserved = 0;
3916 hdr->aiKeyAlg = CALG_RSA_KEYX;
3917 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3918 sizeof(BLOBHEADER));
3919 rsaPubKey->magic = RSA1_MAGIC;
3920 rsaPubKey->pubexp = decodedKey->pubexp;
3921 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3922 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3923 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3924 decodedKey->modulus.cbData);
3926 LocalFree(decodedKey);
3929 __EXCEPT_PAGE_FAULT
3931 SetLastError(STATUS_ACCESS_VIOLATION);
3932 ret = FALSE;
3934 __ENDTRY
3935 return ret;
3938 #define RSA2_MAGIC 0x32415352
3940 struct DECODED_RSA_PRIV_KEY
3942 DWORD version;
3943 DWORD pubexp;
3944 CRYPT_INTEGER_BLOB modulus;
3945 CRYPT_INTEGER_BLOB privexp;
3946 CRYPT_INTEGER_BLOB prime1;
3947 CRYPT_INTEGER_BLOB prime2;
3948 CRYPT_INTEGER_BLOB exponent1;
3949 CRYPT_INTEGER_BLOB exponent2;
3950 CRYPT_INTEGER_BLOB coefficient;
3953 static BOOL WINAPI CRYPT_AsnDecodeRsaPrivKey(DWORD dwCertEncodingType,
3954 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3955 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3957 BOOL ret;
3958 DWORD halflen;
3960 __TRY
3962 struct AsnDecodeSequenceItem items[] = {
3963 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, version),
3964 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3965 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, modulus),
3966 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3967 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, modulus.pbData),
3968 0 },
3969 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, pubexp),
3970 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3971 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, privexp),
3972 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3973 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, privexp.pbData),
3974 0 },
3975 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime1),
3976 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3977 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime1.pbData),
3978 0 },
3979 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime2),
3980 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3981 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime2.pbData),
3982 0 },
3983 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1),
3984 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3985 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1.pbData),
3986 0 },
3987 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2),
3988 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3989 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2.pbData),
3990 0 },
3991 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient),
3992 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3993 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient.pbData),
3994 0 },
3996 struct DECODED_RSA_PRIV_KEY *decodedKey = NULL;
3997 DWORD size = 0;
3999 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
4000 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
4001 &size, NULL, NULL);
4002 if (ret)
4004 halflen = decodedKey->prime1.cbData;
4005 if (halflen < decodedKey->prime2.cbData)
4006 halflen = decodedKey->prime2.cbData;
4007 if (halflen < decodedKey->exponent1.cbData)
4008 halflen = decodedKey->exponent1.cbData;
4009 if (halflen < decodedKey->exponent2.cbData)
4010 halflen = decodedKey->exponent2.cbData;
4011 if (halflen < decodedKey->coefficient.cbData)
4012 halflen = decodedKey->coefficient.cbData;
4013 if (halflen * 2 < decodedKey->modulus.cbData)
4014 halflen = decodedKey->modulus.cbData / 2 + decodedKey->modulus.cbData % 2;
4015 if (halflen * 2 < decodedKey->privexp.cbData)
4016 halflen = decodedKey->privexp.cbData / 2 + decodedKey->privexp.cbData % 2;
4018 if (ret)
4020 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
4021 (halflen * 9);
4023 if (!pvStructInfo)
4025 *pcbStructInfo = bytesNeeded;
4026 ret = TRUE;
4028 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4029 pvStructInfo, pcbStructInfo, bytesNeeded)))
4031 BLOBHEADER *hdr;
4032 RSAPUBKEY *rsaPubKey;
4033 BYTE *vardata;
4035 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4036 pvStructInfo = *(BYTE **)pvStructInfo;
4038 hdr = pvStructInfo;
4039 hdr->bType = PRIVATEKEYBLOB;
4040 hdr->bVersion = CUR_BLOB_VERSION;
4041 hdr->reserved = 0;
4042 hdr->aiKeyAlg = CALG_RSA_KEYX;
4044 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
4045 sizeof(BLOBHEADER));
4046 rsaPubKey->magic = RSA2_MAGIC;
4047 rsaPubKey->pubexp = decodedKey->pubexp;
4048 rsaPubKey->bitlen = halflen * 16;
4050 vardata = (BYTE*)(rsaPubKey + 1);
4051 memset(vardata, 0, halflen * 9);
4052 memcpy(vardata,
4053 decodedKey->modulus.pbData, decodedKey->modulus.cbData);
4054 memcpy(vardata + halflen * 2,
4055 decodedKey->prime1.pbData, decodedKey->prime1.cbData);
4056 memcpy(vardata + halflen * 3,
4057 decodedKey->prime2.pbData, decodedKey->prime2.cbData);
4058 memcpy(vardata + halflen * 4,
4059 decodedKey->exponent1.pbData, decodedKey->exponent1.cbData);
4060 memcpy(vardata + halflen * 5,
4061 decodedKey->exponent2.pbData, decodedKey->exponent2.cbData);
4062 memcpy(vardata + halflen * 6,
4063 decodedKey->coefficient.pbData, decodedKey->coefficient.cbData);
4064 memcpy(vardata + halflen * 7,
4065 decodedKey->privexp.pbData, decodedKey->privexp.cbData);
4069 LocalFree(decodedKey);
4072 __EXCEPT_PAGE_FAULT
4074 SetLastError(STATUS_ACCESS_VIOLATION);
4075 ret = FALSE;
4077 __ENDTRY
4078 return ret;
4081 static BOOL CRYPT_AsnDecodeOctets(const BYTE *pbEncoded,
4082 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4083 DWORD *pcbDecoded)
4085 BOOL ret;
4086 DWORD bytesNeeded, dataLen;
4088 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4089 pvStructInfo, *pcbStructInfo, pcbDecoded);
4091 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4093 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4095 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4096 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
4097 else
4098 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
4099 if (pcbDecoded)
4100 *pcbDecoded = 1 + lenBytes + dataLen;
4101 if (!pvStructInfo)
4102 *pcbStructInfo = bytesNeeded;
4103 else if (*pcbStructInfo < bytesNeeded)
4105 SetLastError(ERROR_MORE_DATA);
4106 *pcbStructInfo = bytesNeeded;
4107 ret = FALSE;
4109 else
4111 CRYPT_DATA_BLOB *blob;
4113 *pcbStructInfo = bytesNeeded;
4114 blob = pvStructInfo;
4115 blob->cbData = dataLen;
4116 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4117 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
4118 else
4120 assert(blob->pbData);
4121 if (blob->cbData)
4122 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
4123 blob->cbData);
4127 return ret;
4130 static BOOL CRYPT_AsnDecodeOctetStringInternal(const BYTE *encoded, DWORD encoded_size,
4131 DWORD flags, void *buf, DWORD *buf_size, DWORD *ret_decoded)
4133 DWORD decoded = 0, indefinite_len_depth = 0, len_size, len, bytes_needed;
4134 CRYPT_DATA_BLOB *blob;
4135 const BYTE *string;
4137 while (encoded[0] == (ASN_CONSTRUCTOR | ASN_OCTETSTRING))
4139 if (!CRYPT_GetLengthIndefinite(encoded, encoded_size, &len))
4140 return FALSE;
4142 len_size = GET_LEN_BYTES(encoded[1]);
4143 encoded += 1 + len_size;
4144 encoded_size -= 1 + len_size;
4145 decoded += 1 + len_size;
4147 if (len == CMSG_INDEFINITE_LENGTH)
4149 indefinite_len_depth++;
4150 if (encoded_size < 2)
4152 SetLastError(CRYPT_E_ASN1_EOD);
4153 return FALSE;
4155 encoded_size -= 2;
4156 decoded += 2;
4160 if (encoded[0] != ASN_OCTETSTRING)
4162 WARN("Unexpected tag %02x\n", encoded[0]);
4163 SetLastError(CRYPT_E_ASN1_BADTAG);
4164 return FALSE;
4167 if (!CRYPT_GetLen(encoded, encoded_size, &len))
4168 return FALSE;
4169 len_size = GET_LEN_BYTES(encoded[1]);
4170 decoded += 1 + len_size + len;
4171 encoded_size -= 1 + len_size;
4173 if (len > encoded_size)
4175 SetLastError(CRYPT_E_ASN1_EOD);
4176 return FALSE;
4178 if (ret_decoded)
4179 *ret_decoded = decoded;
4181 encoded += 1 + len_size;
4182 string = encoded;
4183 encoded += len;
4185 while (indefinite_len_depth--)
4187 if (encoded[0] || encoded[1])
4189 TRACE("expected 0 TLV, got %02x %02x\n", encoded[0], encoded[1]);
4190 SetLastError(CRYPT_E_ASN1_CORRUPT);
4191 return FALSE;
4195 bytes_needed = sizeof(*blob);
4196 if (!(flags & CRYPT_DECODE_NOCOPY_FLAG)) bytes_needed += len;
4197 if (!buf)
4199 *buf_size = bytes_needed;
4200 return TRUE;
4202 if (*buf_size < bytes_needed)
4204 SetLastError(ERROR_MORE_DATA);
4205 *buf_size = bytes_needed;
4206 return FALSE;
4209 *buf_size = bytes_needed;
4210 blob = buf;
4211 blob->cbData = len;
4212 if (flags & CRYPT_DECODE_NOCOPY_FLAG)
4213 blob->pbData = (BYTE*)string;
4214 else if (blob->cbData)
4215 memcpy(blob->pbData, string, blob->cbData);
4217 if (ret_decoded)
4218 *ret_decoded = decoded;
4219 return TRUE;
4222 static BOOL WINAPI CRYPT_AsnDecodeOctetString(DWORD dwCertEncodingType,
4223 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4224 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4226 BOOL ret;
4228 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4229 pDecodePara, pvStructInfo, *pcbStructInfo);
4231 if (!cbEncoded)
4233 SetLastError(CRYPT_E_ASN1_CORRUPT);
4234 return FALSE;
4237 __TRY
4239 DWORD bytesNeeded = 0;
4241 if ((ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded,
4242 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4244 if (!pvStructInfo)
4245 *pcbStructInfo = bytesNeeded;
4246 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4247 pvStructInfo, pcbStructInfo, bytesNeeded)))
4249 CRYPT_DATA_BLOB *blob;
4251 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4252 pvStructInfo = *(BYTE **)pvStructInfo;
4253 blob = pvStructInfo;
4254 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
4255 ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded,
4256 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4257 &bytesNeeded, NULL);
4258 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4259 CRYPT_FreeSpace(pDecodePara, blob);
4263 __EXCEPT_PAGE_FAULT
4265 SetLastError(STATUS_ACCESS_VIOLATION);
4266 ret = FALSE;
4268 __ENDTRY
4269 return ret;
4272 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4273 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4275 BOOL ret;
4276 DWORD bytesNeeded, dataLen;
4277 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4279 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
4280 pvStructInfo, *pcbStructInfo, pcbDecoded);
4282 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4284 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4285 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
4286 else
4287 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
4288 if (pcbDecoded)
4289 *pcbDecoded = 1 + lenBytes + dataLen;
4290 if (!pvStructInfo)
4291 *pcbStructInfo = bytesNeeded;
4292 else if (*pcbStructInfo < bytesNeeded)
4294 *pcbStructInfo = bytesNeeded;
4295 SetLastError(ERROR_MORE_DATA);
4296 ret = FALSE;
4298 else
4300 CRYPT_BIT_BLOB *blob;
4302 *pcbStructInfo = bytesNeeded;
4303 blob = pvStructInfo;
4304 blob->cbData = dataLen - 1;
4305 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
4306 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4308 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
4310 else
4312 assert(blob->pbData);
4313 if (blob->cbData)
4315 BYTE mask = 0xff << blob->cUnusedBits;
4317 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
4318 blob->cbData);
4319 blob->pbData[blob->cbData - 1] &= mask;
4324 return ret;
4327 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
4328 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4329 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4331 BOOL ret;
4333 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
4334 pDecodePara, pvStructInfo, pcbStructInfo);
4336 __TRY
4338 DWORD bytesNeeded = 0;
4340 if (!cbEncoded)
4342 SetLastError(CRYPT_E_ASN1_CORRUPT);
4343 ret = FALSE;
4345 else if (pbEncoded[0] != ASN_BITSTRING)
4347 SetLastError(CRYPT_E_ASN1_BADTAG);
4348 ret = FALSE;
4350 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4351 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4353 if (!pvStructInfo)
4354 *pcbStructInfo = bytesNeeded;
4355 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4356 pvStructInfo, pcbStructInfo, bytesNeeded)))
4358 CRYPT_BIT_BLOB *blob;
4360 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4361 pvStructInfo = *(BYTE **)pvStructInfo;
4362 blob = pvStructInfo;
4363 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
4364 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4365 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4366 &bytesNeeded, NULL);
4367 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4368 CRYPT_FreeSpace(pDecodePara, blob);
4372 __EXCEPT_PAGE_FAULT
4374 SetLastError(STATUS_ACCESS_VIOLATION);
4375 ret = FALSE;
4377 __ENDTRY
4378 TRACE("returning %d (%08x)\n", ret, GetLastError());
4379 return ret;
4382 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
4383 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4384 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4386 BOOL ret;
4387 DWORD dataLen;
4389 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4391 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4393 if (pcbDecoded)
4394 *pcbDecoded = 1 + lenBytes + dataLen;
4395 if (dataLen > sizeof(int))
4397 SetLastError(CRYPT_E_ASN1_LARGE);
4398 ret = FALSE;
4400 else if (!pvStructInfo)
4401 *pcbStructInfo = sizeof(int);
4402 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
4404 int val, i;
4406 if (dataLen && pbEncoded[1 + lenBytes] & 0x80)
4408 /* initialize to a negative value to sign-extend */
4409 val = -1;
4411 else
4412 val = 0;
4413 for (i = 0; i < dataLen; i++)
4415 val <<= 8;
4416 val |= pbEncoded[1 + lenBytes + i];
4418 memcpy(pvStructInfo, &val, sizeof(int));
4421 return ret;
4424 static BOOL WINAPI CRYPT_AsnDecodeInt(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 __TRY
4432 DWORD bytesNeeded = 0;
4434 if (!cbEncoded)
4436 SetLastError(CRYPT_E_ASN1_EOD);
4437 ret = FALSE;
4439 else if (pbEncoded[0] != ASN_INTEGER)
4441 SetLastError(CRYPT_E_ASN1_BADTAG);
4442 ret = FALSE;
4444 else
4445 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4446 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4447 if (ret)
4449 if (!pvStructInfo)
4450 *pcbStructInfo = bytesNeeded;
4451 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4452 pvStructInfo, pcbStructInfo, bytesNeeded)))
4454 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4455 pvStructInfo = *(BYTE **)pvStructInfo;
4456 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4457 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4458 &bytesNeeded, NULL);
4459 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4460 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
4464 __EXCEPT_PAGE_FAULT
4466 SetLastError(STATUS_ACCESS_VIOLATION);
4467 ret = FALSE;
4469 __ENDTRY
4470 return ret;
4473 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
4474 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4475 DWORD *pcbDecoded)
4477 BOOL ret;
4478 DWORD bytesNeeded, dataLen;
4480 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4482 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4484 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4485 if (pcbDecoded)
4486 *pcbDecoded = 1 + lenBytes + dataLen;
4487 if (!pvStructInfo)
4488 *pcbStructInfo = bytesNeeded;
4489 else if (*pcbStructInfo < bytesNeeded)
4491 *pcbStructInfo = bytesNeeded;
4492 SetLastError(ERROR_MORE_DATA);
4493 ret = FALSE;
4495 else
4497 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4499 *pcbStructInfo = bytesNeeded;
4500 blob->cbData = dataLen;
4501 assert(blob->pbData);
4502 if (blob->cbData)
4504 DWORD i;
4506 for (i = 0; i < blob->cbData; i++)
4508 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4509 dataLen - i - 1);
4514 return ret;
4517 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4518 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4519 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4521 BOOL ret;
4523 __TRY
4525 DWORD bytesNeeded = 0;
4527 if (pbEncoded[0] != ASN_INTEGER)
4529 SetLastError(CRYPT_E_ASN1_BADTAG);
4530 ret = FALSE;
4532 else
4533 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4534 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4535 if (ret)
4537 if (!pvStructInfo)
4538 *pcbStructInfo = bytesNeeded;
4539 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4540 pvStructInfo, pcbStructInfo, bytesNeeded)))
4542 CRYPT_INTEGER_BLOB *blob;
4544 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4545 pvStructInfo = *(BYTE **)pvStructInfo;
4546 blob = pvStructInfo;
4547 blob->pbData = (BYTE *)pvStructInfo +
4548 sizeof(CRYPT_INTEGER_BLOB);
4549 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4550 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4551 &bytesNeeded, NULL);
4552 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4553 CRYPT_FreeSpace(pDecodePara, blob);
4557 __EXCEPT_PAGE_FAULT
4559 SetLastError(STATUS_ACCESS_VIOLATION);
4560 ret = FALSE;
4562 __ENDTRY
4563 return ret;
4566 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
4567 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4568 DWORD *pcbDecoded)
4570 BOOL ret;
4572 if (pbEncoded[0] == ASN_INTEGER)
4574 DWORD bytesNeeded, dataLen;
4576 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4578 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4580 if (pcbDecoded)
4581 *pcbDecoded = 1 + lenBytes + dataLen;
4582 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4583 if (!pvStructInfo)
4584 *pcbStructInfo = bytesNeeded;
4585 else if (*pcbStructInfo < bytesNeeded)
4587 *pcbStructInfo = bytesNeeded;
4588 SetLastError(ERROR_MORE_DATA);
4589 ret = FALSE;
4591 else
4593 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4595 *pcbStructInfo = bytesNeeded;
4596 blob->cbData = dataLen;
4597 assert(blob->pbData);
4598 /* remove leading zero byte if it exists */
4599 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4601 blob->cbData--;
4602 blob->pbData++;
4604 if (blob->cbData)
4606 DWORD i;
4608 for (i = 0; i < blob->cbData; i++)
4610 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4611 dataLen - i - 1);
4617 else
4619 SetLastError(CRYPT_E_ASN1_BADTAG);
4620 ret = FALSE;
4622 return ret;
4625 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4626 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4627 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4629 BOOL ret;
4631 __TRY
4633 DWORD bytesNeeded = 0;
4635 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4636 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4638 if (!pvStructInfo)
4639 *pcbStructInfo = bytesNeeded;
4640 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4641 pvStructInfo, pcbStructInfo, bytesNeeded)))
4643 CRYPT_INTEGER_BLOB *blob;
4645 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4646 pvStructInfo = *(BYTE **)pvStructInfo;
4647 blob = pvStructInfo;
4648 blob->pbData = (BYTE *)pvStructInfo +
4649 sizeof(CRYPT_INTEGER_BLOB);
4650 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4651 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4652 &bytesNeeded, NULL);
4653 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4654 CRYPT_FreeSpace(pDecodePara, blob);
4658 __EXCEPT_PAGE_FAULT
4660 SetLastError(STATUS_ACCESS_VIOLATION);
4661 ret = FALSE;
4663 __ENDTRY
4664 return ret;
4667 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4668 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4669 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4671 BOOL ret;
4673 if (!pvStructInfo)
4675 *pcbStructInfo = sizeof(int);
4676 return TRUE;
4678 __TRY
4680 if (pbEncoded[0] == ASN_ENUMERATED)
4682 unsigned int val = 0, i;
4684 if (cbEncoded <= 1)
4686 SetLastError(CRYPT_E_ASN1_EOD);
4687 ret = FALSE;
4689 else if (pbEncoded[1] == 0)
4691 SetLastError(CRYPT_E_ASN1_CORRUPT);
4692 ret = FALSE;
4694 else
4696 /* A little strange looking, but we have to accept a sign byte:
4697 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4698 * assuming a small length is okay here, it has to be in short
4699 * form.
4701 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4703 SetLastError(CRYPT_E_ASN1_LARGE);
4704 return FALSE;
4706 for (i = 0; i < pbEncoded[1]; i++)
4708 val <<= 8;
4709 val |= pbEncoded[2 + i];
4711 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4712 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4714 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4715 pvStructInfo = *(BYTE **)pvStructInfo;
4716 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4720 else
4722 SetLastError(CRYPT_E_ASN1_BADTAG);
4723 ret = FALSE;
4726 __EXCEPT_PAGE_FAULT
4728 SetLastError(STATUS_ACCESS_VIOLATION);
4729 ret = FALSE;
4731 __ENDTRY
4732 return ret;
4735 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4736 * if it fails.
4738 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4739 do { \
4740 BYTE i; \
4742 (word) = 0; \
4743 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4745 if (!isdigit(*(pbEncoded))) \
4747 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4748 ret = FALSE; \
4750 else \
4752 (word) *= 10; \
4753 (word) += *(pbEncoded)++ - '0'; \
4756 } while (0)
4758 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4759 SYSTEMTIME *sysTime)
4761 BOOL ret = TRUE;
4763 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4765 WORD hours, minutes = 0;
4766 BYTE sign = *pbEncoded++;
4768 len--;
4769 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4770 if (ret && hours >= 24)
4772 SetLastError(CRYPT_E_ASN1_CORRUPT);
4773 ret = FALSE;
4775 else if (len >= 2)
4777 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4778 if (ret && minutes >= 60)
4780 SetLastError(CRYPT_E_ASN1_CORRUPT);
4781 ret = FALSE;
4784 if (ret)
4786 if (sign == '+')
4788 sysTime->wHour += hours;
4789 sysTime->wMinute += minutes;
4791 else
4793 if (hours > sysTime->wHour)
4795 sysTime->wDay--;
4796 sysTime->wHour = 24 - (hours - sysTime->wHour);
4798 else
4799 sysTime->wHour -= hours;
4800 if (minutes > sysTime->wMinute)
4802 sysTime->wHour--;
4803 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4805 else
4806 sysTime->wMinute -= minutes;
4810 return ret;
4813 #define MIN_ENCODED_TIME_LENGTH 10
4815 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4816 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4817 DWORD *pcbDecoded)
4819 BOOL ret = FALSE;
4821 if (pbEncoded[0] == ASN_UTCTIME)
4823 if (cbEncoded <= 1)
4824 SetLastError(CRYPT_E_ASN1_EOD);
4825 else if (pbEncoded[1] > 0x7f)
4827 /* long-form date strings really can't be valid */
4828 SetLastError(CRYPT_E_ASN1_CORRUPT);
4830 else
4832 SYSTEMTIME sysTime = { 0 };
4833 BYTE len = pbEncoded[1];
4835 if (len < MIN_ENCODED_TIME_LENGTH)
4836 SetLastError(CRYPT_E_ASN1_CORRUPT);
4837 else
4839 ret = TRUE;
4840 if (pcbDecoded)
4841 *pcbDecoded = 2 + len;
4842 pbEncoded += 2;
4843 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4844 if (sysTime.wYear >= 50)
4845 sysTime.wYear += 1900;
4846 else
4847 sysTime.wYear += 2000;
4848 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4849 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4850 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4851 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4852 if (ret && len > 0)
4854 if (len >= 2 && isdigit(*pbEncoded) &&
4855 isdigit(*(pbEncoded + 1)))
4856 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4857 sysTime.wSecond);
4858 else if (isdigit(*pbEncoded))
4859 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4860 sysTime.wSecond);
4861 if (ret)
4862 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4863 &sysTime);
4865 if (ret)
4867 if (!pvStructInfo)
4868 *pcbStructInfo = sizeof(FILETIME);
4869 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4870 sizeof(FILETIME))))
4871 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4876 else
4877 SetLastError(CRYPT_E_ASN1_BADTAG);
4878 return ret;
4881 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4882 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4883 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4885 BOOL ret = FALSE;
4887 __TRY
4889 DWORD bytesNeeded = 0;
4891 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4892 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4893 if (ret)
4895 if (!pvStructInfo)
4896 *pcbStructInfo = bytesNeeded;
4897 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4898 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4900 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4901 pvStructInfo = *(BYTE **)pvStructInfo;
4902 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4903 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4904 &bytesNeeded, NULL);
4905 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4906 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
4910 __EXCEPT_PAGE_FAULT
4912 SetLastError(STATUS_ACCESS_VIOLATION);
4914 __ENDTRY
4915 return ret;
4918 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
4919 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4920 DWORD *pcbDecoded)
4922 BOOL ret = FALSE;
4924 if (pbEncoded[0] == ASN_GENERALTIME)
4926 if (cbEncoded <= 1)
4927 SetLastError(CRYPT_E_ASN1_EOD);
4928 else if (pbEncoded[1] > 0x7f)
4930 /* long-form date strings really can't be valid */
4931 SetLastError(CRYPT_E_ASN1_CORRUPT);
4933 else
4935 BYTE len = pbEncoded[1];
4937 if (len < MIN_ENCODED_TIME_LENGTH)
4938 SetLastError(CRYPT_E_ASN1_CORRUPT);
4939 else
4941 SYSTEMTIME sysTime = { 0 };
4943 ret = TRUE;
4944 if (pcbDecoded)
4945 *pcbDecoded = 2 + len;
4946 pbEncoded += 2;
4947 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
4948 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4949 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4950 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4951 if (ret && len > 0)
4953 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4954 sysTime.wMinute);
4955 if (ret && len > 0)
4956 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4957 sysTime.wSecond);
4958 if (ret && len > 0 && (*pbEncoded == '.' ||
4959 *pbEncoded == ','))
4961 BYTE digits;
4963 pbEncoded++;
4964 len--;
4965 /* workaround macro weirdness */
4966 digits = min(len, 3);
4967 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
4968 sysTime.wMilliseconds);
4970 if (ret)
4971 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4972 &sysTime);
4974 if (ret)
4976 if (!pvStructInfo)
4977 *pcbStructInfo = sizeof(FILETIME);
4978 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4979 sizeof(FILETIME))))
4980 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4985 else
4986 SetLastError(CRYPT_E_ASN1_BADTAG);
4987 return ret;
4990 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4991 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4992 DWORD *pcbDecoded)
4994 BOOL ret;
4995 InternalDecodeFunc decode = NULL;
4997 if (pbEncoded[0] == ASN_UTCTIME)
4998 decode = CRYPT_AsnDecodeUtcTimeInternal;
4999 else if (pbEncoded[0] == ASN_GENERALTIME)
5000 decode = CRYPT_AsnDecodeGeneralizedTime;
5001 if (decode)
5002 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
5003 pcbStructInfo, pcbDecoded);
5004 else
5006 SetLastError(CRYPT_E_ASN1_BADTAG);
5007 ret = FALSE;
5009 return ret;
5012 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
5013 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5014 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5016 BOOL ret;
5018 __TRY
5020 DWORD bytesNeeded = 0;
5022 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
5023 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
5024 if (ret)
5026 if (!pvStructInfo)
5027 *pcbStructInfo = bytesNeeded;
5028 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5029 pvStructInfo, pcbStructInfo, bytesNeeded)))
5031 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5032 pvStructInfo = *(BYTE **)pvStructInfo;
5033 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
5034 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5035 &bytesNeeded, NULL);
5036 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5037 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
5041 __EXCEPT_PAGE_FAULT
5043 SetLastError(STATUS_ACCESS_VIOLATION);
5044 ret = FALSE;
5046 __ENDTRY
5047 return ret;
5050 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
5051 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5052 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5054 BOOL ret = TRUE;
5056 __TRY
5058 if (pbEncoded[0] == ASN_SEQUENCEOF)
5060 DWORD bytesNeeded, dataLen, remainingLen, cValue;
5062 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5064 BYTE lenBytes;
5065 const BYTE *ptr;
5067 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5068 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
5069 cValue = 0;
5070 ptr = pbEncoded + 1 + lenBytes;
5071 remainingLen = dataLen;
5072 while (ret && remainingLen)
5074 DWORD nextLen;
5076 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5077 if (ret)
5079 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5081 remainingLen -= 1 + nextLenBytes + nextLen;
5082 ptr += 1 + nextLenBytes + nextLen;
5083 bytesNeeded += sizeof(CRYPT_DER_BLOB);
5084 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
5085 bytesNeeded += 1 + nextLenBytes + nextLen;
5086 cValue++;
5089 if (ret)
5091 CRYPT_SEQUENCE_OF_ANY *seq;
5092 BYTE *nextPtr;
5093 DWORD i;
5095 if (!pvStructInfo)
5096 *pcbStructInfo = bytesNeeded;
5097 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5098 pvStructInfo, pcbStructInfo, bytesNeeded)))
5100 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5101 pvStructInfo = *(BYTE **)pvStructInfo;
5102 seq = pvStructInfo;
5103 seq->cValue = cValue;
5104 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
5105 sizeof(*seq));
5106 nextPtr = (BYTE *)seq->rgValue +
5107 cValue * sizeof(CRYPT_DER_BLOB);
5108 ptr = pbEncoded + 1 + lenBytes;
5109 remainingLen = dataLen;
5110 i = 0;
5111 while (ret && remainingLen)
5113 DWORD nextLen;
5115 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5116 if (ret)
5118 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5120 seq->rgValue[i].cbData = 1 + nextLenBytes +
5121 nextLen;
5122 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
5123 seq->rgValue[i].pbData = (BYTE *)ptr;
5124 else
5126 seq->rgValue[i].pbData = nextPtr;
5127 memcpy(nextPtr, ptr, 1 + nextLenBytes +
5128 nextLen);
5129 nextPtr += 1 + nextLenBytes + nextLen;
5131 remainingLen -= 1 + nextLenBytes + nextLen;
5132 ptr += 1 + nextLenBytes + nextLen;
5133 i++;
5136 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5137 CRYPT_FreeSpace(pDecodePara, seq);
5142 else
5144 SetLastError(CRYPT_E_ASN1_BADTAG);
5145 ret = FALSE;
5148 __EXCEPT_PAGE_FAULT
5150 SetLastError(STATUS_ACCESS_VIOLATION);
5151 ret = FALSE;
5153 __ENDTRY
5154 return ret;
5157 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
5158 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5159 DWORD *pcbDecoded)
5161 BOOL ret;
5163 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
5165 DWORD bytesNeeded = 0, dataLen;
5167 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5169 struct AsnArrayDescriptor arrayDesc = {
5170 ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5171 offsetof(CRL_DIST_POINT_NAME, u.FullName.cAltEntry),
5172 offsetof(CRL_DIST_POINT_NAME, u.FullName.rgAltEntry),
5173 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u),
5174 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
5175 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
5176 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5177 DWORD nameLen;
5179 if (dataLen)
5181 ret = CRYPT_AsnDecodeArray(&arrayDesc,
5182 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
5183 dwFlags, NULL, NULL, &nameLen, NULL);
5184 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
5185 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u);
5187 else
5188 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
5189 if (pcbDecoded)
5190 *pcbDecoded = 1 + lenBytes + dataLen;
5191 if (!pvStructInfo)
5192 *pcbStructInfo = bytesNeeded;
5193 else if (*pcbStructInfo < bytesNeeded)
5195 *pcbStructInfo = bytesNeeded;
5196 SetLastError(ERROR_MORE_DATA);
5197 ret = FALSE;
5199 else
5201 CRL_DIST_POINT_NAME *name = pvStructInfo;
5203 *pcbStructInfo = bytesNeeded;
5204 if (dataLen)
5206 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
5207 ret = CRYPT_AsnDecodeArray(&arrayDesc,
5208 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
5209 dwFlags, NULL, &name->u.FullName.cAltEntry, &nameLen,
5210 NULL);
5212 else
5213 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
5217 else
5219 SetLastError(CRYPT_E_ASN1_BADTAG);
5220 ret = FALSE;
5222 return ret;
5225 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
5226 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5228 struct AsnDecodeSequenceItem items[] = {
5229 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
5230 DistPointName), CRYPT_AsnDecodeDistPointName,
5231 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
5232 DistPointName.u.FullName.rgAltEntry), 0 },
5233 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
5234 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
5235 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
5236 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
5237 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
5238 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
5240 CRL_DIST_POINT *point = pvStructInfo;
5241 BOOL ret;
5243 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5244 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5245 pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
5246 return ret;
5249 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
5250 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5251 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5253 BOOL ret;
5255 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5256 pDecodePara, pvStructInfo, *pcbStructInfo);
5258 __TRY
5260 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5261 offsetof(CRL_DIST_POINTS_INFO, cDistPoint),
5262 offsetof(CRL_DIST_POINTS_INFO, rgDistPoint),
5263 sizeof(CRL_DIST_POINTS_INFO),
5264 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
5265 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
5266 CRL_DIST_POINTS_INFO *info = pvStructInfo;
5268 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5269 info->rgDistPoint = (CRL_DIST_POINT *)(info + 1);
5270 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5271 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
5273 __EXCEPT_PAGE_FAULT
5275 SetLastError(STATUS_ACCESS_VIOLATION);
5276 ret = FALSE;
5278 __ENDTRY
5279 return ret;
5282 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
5283 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5284 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5286 BOOL ret;
5288 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5289 pDecodePara, pvStructInfo, *pcbStructInfo);
5291 __TRY
5293 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5294 offsetof(CERT_ENHKEY_USAGE, cUsageIdentifier),
5295 offsetof(CERT_ENHKEY_USAGE, rgpszUsageIdentifier),
5296 sizeof(CERT_ENHKEY_USAGE),
5297 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
5298 CERT_ENHKEY_USAGE *usage = pvStructInfo;
5300 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5301 usage->rgpszUsageIdentifier = (LPSTR *)(usage + 1);
5302 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5303 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
5305 __EXCEPT_PAGE_FAULT
5307 SetLastError(STATUS_ACCESS_VIOLATION);
5308 ret = FALSE;
5310 __ENDTRY
5311 return ret;
5314 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
5315 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5316 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5318 BOOL ret;
5320 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5321 pDecodePara, pvStructInfo, *pcbStructInfo);
5323 __TRY
5325 struct AsnDecodeSequenceItem items[] = {
5326 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
5327 DistPointName), CRYPT_AsnDecodeDistPointName,
5328 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
5329 offsetof(CRL_ISSUING_DIST_POINT,
5330 DistPointName.u.FullName.rgAltEntry), 0 },
5331 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
5332 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5333 FALSE, 0 },
5334 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
5335 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5336 FALSE, 0 },
5337 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
5338 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
5339 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
5340 OnlySomeReasonFlags.pbData), 0 },
5341 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
5342 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
5345 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5346 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5347 pcbStructInfo, NULL, NULL);
5349 __EXCEPT_PAGE_FAULT
5351 SetLastError(STATUS_ACCESS_VIOLATION);
5352 ret = FALSE;
5354 __ENDTRY
5355 return ret;
5358 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
5359 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5360 DWORD *pcbDecoded)
5362 BOOL ret;
5363 DWORD max, size = sizeof(max);
5365 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5366 pvStructInfo, *pcbStructInfo, pcbDecoded);
5368 if (!cbEncoded)
5370 SetLastError(CRYPT_E_ASN1_EOD);
5371 return FALSE;
5373 if (pbEncoded[0] != (ASN_CONTEXT | 1))
5375 SetLastError(CRYPT_E_ASN1_BADTAG);
5376 return FALSE;
5378 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
5379 &max, &size, pcbDecoded)))
5381 DWORD bytesNeeded = FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum);
5383 if (!pvStructInfo)
5384 *pcbStructInfo = bytesNeeded;
5385 else if (*pcbStructInfo < bytesNeeded)
5387 *pcbStructInfo = bytesNeeded;
5388 SetLastError(ERROR_MORE_DATA);
5389 ret = FALSE;
5391 else
5393 CERT_GENERAL_SUBTREE *subtree = CONTAINING_RECORD(pvStructInfo,
5394 CERT_GENERAL_SUBTREE, fMaximum);
5396 *pcbStructInfo = bytesNeeded;
5397 /* The BOOL is implicit: if the integer is present, then it's
5398 * TRUE.
5400 subtree->fMaximum = TRUE;
5401 subtree->dwMaximum = max;
5404 TRACE("returning %d\n", ret);
5405 return ret;
5408 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
5409 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5410 DWORD *pcbDecoded)
5412 BOOL ret;
5413 struct AsnDecodeSequenceItem items[] = {
5414 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
5415 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
5416 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
5417 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
5418 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
5419 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
5420 CRYPT_AsnDecodeMaximum, FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum),
5421 TRUE, FALSE, 0, 0 },
5423 CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
5425 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5426 pvStructInfo, *pcbStructInfo, pcbDecoded);
5428 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5429 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5430 pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
5431 if (pcbDecoded)
5433 TRACE("%d\n", *pcbDecoded);
5434 if (*pcbDecoded < cbEncoded)
5435 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
5436 *(pbEncoded + *pcbDecoded + 1));
5438 TRACE("returning %d\n", ret);
5439 return ret;
5442 static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
5443 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5444 DWORD *pcbDecoded)
5446 BOOL ret = TRUE;
5447 struct AsnArrayDescriptor arrayDesc = { 0,
5448 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5449 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree),
5450 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5451 cExcludedSubtree),
5452 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5453 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5455 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5456 pvStructInfo, *pcbStructInfo, pcbDecoded);
5458 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5459 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5460 return ret;
5463 static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
5464 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5465 DWORD *pcbDecoded)
5467 BOOL ret = TRUE;
5468 struct AsnArrayDescriptor arrayDesc = { 0,
5469 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5470 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree),
5471 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5472 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5473 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5475 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5476 pvStructInfo, *pcbStructInfo, pcbDecoded);
5478 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5479 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5480 return ret;
5483 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
5484 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5485 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5487 BOOL ret = FALSE;
5489 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5490 pDecodePara, pvStructInfo, *pcbStructInfo);
5492 __TRY
5494 struct AsnDecodeSequenceItem items[] = {
5495 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5496 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5497 CRYPT_AsnDecodePermittedSubtree,
5498 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5499 cExcludedSubtree), TRUE, TRUE,
5500 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
5501 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
5502 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5503 CRYPT_AsnDecodeExcludedSubtree,
5504 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5505 TRUE, TRUE,
5506 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
5509 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5510 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5511 pcbStructInfo, NULL, NULL);
5513 __EXCEPT_PAGE_FAULT
5515 SetLastError(STATUS_ACCESS_VIOLATION);
5517 __ENDTRY
5518 return ret;
5521 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
5522 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5523 DWORD *pcbDecoded)
5525 BOOL ret;
5526 struct AsnDecodeSequenceItem items[] = {
5527 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
5528 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
5529 Issuer.pbData) },
5530 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
5531 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
5532 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
5534 CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
5536 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5537 pvStructInfo, *pcbStructInfo, pcbDecoded);
5539 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5540 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5541 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
5542 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
5544 SetLastError(CRYPT_E_ASN1_CORRUPT);
5545 ret = FALSE;
5547 TRACE("returning %d\n", ret);
5548 return ret;
5551 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
5552 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5553 DWORD *pcbDecoded)
5555 CMSG_SIGNER_INFO *info = pvStructInfo;
5556 struct AsnDecodeSequenceItem items[] = {
5557 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
5558 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5559 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
5560 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
5561 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
5562 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
5563 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5564 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5565 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5566 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
5567 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5568 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5569 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
5570 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5571 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
5572 HashEncryptionAlgorithm.pszObjId), 0 },
5573 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
5574 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
5575 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
5576 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5577 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
5578 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5579 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5581 BOOL ret;
5583 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5584 pvStructInfo, *pcbStructInfo);
5586 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5587 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5588 pcbDecoded, info ? info->Issuer.pbData : NULL);
5589 return ret;
5592 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
5593 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5594 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5596 BOOL ret = FALSE;
5598 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5599 pDecodePara, pvStructInfo, *pcbStructInfo);
5601 __TRY
5603 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
5604 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5605 if (ret && pvStructInfo)
5607 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5608 pcbStructInfo, *pcbStructInfo);
5609 if (ret)
5611 CMSG_SIGNER_INFO *info;
5613 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5614 pvStructInfo = *(BYTE **)pvStructInfo;
5615 info = pvStructInfo;
5616 info->Issuer.pbData = ((BYTE *)info +
5617 sizeof(CMSG_SIGNER_INFO));
5618 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
5619 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5620 pcbStructInfo, NULL);
5621 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5622 CRYPT_FreeSpace(pDecodePara, info);
5626 __EXCEPT_PAGE_FAULT
5628 SetLastError(STATUS_ACCESS_VIOLATION);
5630 __ENDTRY
5631 TRACE("returning %d\n", ret);
5632 return ret;
5635 static BOOL verify_and_copy_certificate(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5636 void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5638 PCCERT_CONTEXT cert;
5640 cert = CertCreateCertificateContext(X509_ASN_ENCODING, pbEncoded, cbEncoded);
5641 if (!cert)
5643 WARN("CertCreateCertificateContext error %#x\n", GetLastError());
5644 *pcbStructInfo = 0;
5645 *pcbDecoded = 0;
5646 return TRUE;
5649 CertFreeCertificateContext(cert);
5651 return CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, pcbDecoded);
5654 static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
5655 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5656 DWORD *pcbDecoded)
5658 BOOL ret;
5659 struct AsnArrayDescriptor arrayDesc = { 0,
5660 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
5661 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded),
5662 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded),
5663 verify_and_copy_certificate,
5664 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5666 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5667 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5669 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5670 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5671 return ret;
5674 static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
5675 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5676 DWORD *pcbDecoded)
5678 BOOL ret;
5679 struct AsnArrayDescriptor arrayDesc = { 0,
5680 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded),
5681 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded),
5682 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content),
5683 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB),
5684 TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5686 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5687 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5689 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5690 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5691 return ret;
5694 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
5695 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5696 DWORD *pcbDecoded)
5698 CERT_ID *id = pvStructInfo;
5699 BOOL ret = FALSE;
5701 if (*pbEncoded == ASN_SEQUENCEOF)
5703 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
5704 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
5705 if (ret)
5707 if (id)
5708 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5709 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
5710 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5711 sizeof(CERT_ISSUER_SERIAL_NUMBER);
5712 else
5713 *pcbStructInfo = sizeof(CERT_ID);
5716 else if (*pbEncoded == (ASN_CONTEXT | 0))
5718 ret = CRYPT_AsnDecodeOctets(pbEncoded, cbEncoded, dwFlags,
5719 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
5720 if (ret)
5722 if (id)
5723 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
5724 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
5725 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5726 sizeof(CRYPT_DATA_BLOB);
5727 else
5728 *pcbStructInfo = sizeof(CERT_ID);
5731 else
5732 SetLastError(CRYPT_E_ASN1_BADTAG);
5733 return ret;
5736 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5737 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5738 DWORD *pcbDecoded)
5740 CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
5741 struct AsnDecodeSequenceItem items[] = {
5742 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5743 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5744 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5745 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5746 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
5747 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5748 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5749 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5750 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5751 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5752 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5753 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5754 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5755 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5756 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5757 HashEncryptionAlgorithm.pszObjId), 0 },
5758 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5759 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
5760 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5761 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5762 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5763 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5764 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5766 BOOL ret;
5768 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5769 pvStructInfo, *pcbStructInfo);
5771 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5772 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5773 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
5774 return ret;
5777 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5778 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5779 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5781 BOOL ret = FALSE;
5783 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5784 pDecodePara, pvStructInfo, *pcbStructInfo);
5786 __TRY
5788 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5789 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5790 if (ret && pvStructInfo)
5792 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5793 pcbStructInfo, *pcbStructInfo);
5794 if (ret)
5796 CMSG_CMS_SIGNER_INFO *info;
5798 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5799 pvStructInfo = *(BYTE **)pvStructInfo;
5800 info = pvStructInfo;
5801 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
5802 sizeof(CMSG_CMS_SIGNER_INFO));
5803 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5804 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5805 pcbStructInfo, NULL);
5806 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5807 CRYPT_FreeSpace(pDecodePara, info);
5811 __EXCEPT_PAGE_FAULT
5813 SetLastError(STATUS_ACCESS_VIOLATION);
5815 __ENDTRY
5816 TRACE("returning %d\n", ret);
5817 return ret;
5820 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5821 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5823 BOOL ret;
5824 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5825 offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5826 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo),
5827 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo),
5828 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5829 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
5831 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5832 pvStructInfo, *pcbStructInfo, pcbDecoded);
5834 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5835 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5836 return ret;
5839 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5840 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5841 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5843 BOOL ret = FALSE;
5844 struct AsnDecodeSequenceItem items[] = {
5845 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5846 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5847 /* Placeholder for the hash algorithms - redundant with those in the
5848 * signers, so just ignore them.
5850 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5851 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5852 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5853 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5854 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5855 offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
5856 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
5857 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5858 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5859 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
5860 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
5861 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5862 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5863 CRYPT_DecodeSignerArray,
5864 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE,
5865 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5868 TRACE("%p, %d, %08x, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags,
5869 pDecodePara, signedInfo, pcbSignedInfo);
5871 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5872 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5873 NULL, NULL);
5874 TRACE("returning %d\n", ret);
5875 return ret;
5878 static BOOL CRYPT_AsnDecodeRecipientInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5879 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5881 BOOL ret;
5882 CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
5883 struct AsnDecodeSequenceItem items[] = {
5884 { ASN_INTEGER, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, dwVersion),
5885 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5886 { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5887 RecipientId.u.IssuerSerialNumber), CRYPT_AsnDecodeIssuerSerialNumber,
5888 sizeof(CERT_ISSUER_SERIAL_NUMBER), FALSE, TRUE,
5889 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5890 RecipientId.u.IssuerSerialNumber.Issuer.pbData), 0 },
5891 { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5892 KeyEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
5893 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
5894 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5895 KeyEncryptionAlgorithm.pszObjId), 0 },
5896 { ASN_OCTETSTRING, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey),
5897 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
5898 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey.pbData), 0 },
5901 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5902 pvStructInfo, *pcbStructInfo, pcbDecoded);
5904 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5905 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5906 pcbDecoded, info ? info->RecipientId.u.IssuerSerialNumber.Issuer.pbData :
5907 NULL);
5908 if (info)
5909 info->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5910 TRACE("returning %d\n", ret);
5911 return ret;
5914 static BOOL CRYPT_DecodeRecipientInfoArray(const BYTE *pbEncoded,
5915 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5916 DWORD *pcbDecoded)
5918 BOOL ret;
5919 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5920 offsetof(CRYPT_ENVELOPED_DATA, cRecipientInfo),
5921 offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo),
5922 MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
5923 CRYPT_AsnDecodeRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), TRUE,
5924 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5925 RecipientId.u.IssuerSerialNumber.Issuer.pbData) };
5927 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5928 pvStructInfo, *pcbStructInfo, pcbDecoded);
5930 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5931 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5932 TRACE("returning %d\n", ret);
5933 return ret;
5936 static BOOL CRYPT_AsnDecodeEncryptedContentInfo(const BYTE *pbEncoded,
5937 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5938 DWORD *pcbDecoded)
5940 BOOL ret;
5941 CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
5942 struct AsnDecodeSequenceItem items[] = {
5943 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5944 contentType), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
5945 FALSE, TRUE, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5946 contentType), 0 },
5947 { ASN_SEQUENCEOF, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5948 contentEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
5949 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
5950 offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5951 contentEncryptionAlgorithm.pszObjId), 0 },
5952 { ASN_CONTEXT | 0, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5953 encryptedContent), CRYPT_AsnDecodeOctets,
5954 sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
5955 offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, encryptedContent.pbData) },
5958 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5959 pvStructInfo, *pcbStructInfo, pcbDecoded);
5961 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5962 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5963 pcbDecoded, info ? info->contentType : NULL);
5964 TRACE("returning %d\n", ret);
5965 return ret;
5968 BOOL CRYPT_AsnDecodePKCSEnvelopedData(const BYTE *pbEncoded, DWORD cbEncoded,
5969 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5970 CRYPT_ENVELOPED_DATA *envelopedData, DWORD *pcbEnvelopedData)
5972 BOOL ret;
5973 struct AsnDecodeSequenceItem items[] = {
5974 { ASN_INTEGER, offsetof(CRYPT_ENVELOPED_DATA, version),
5975 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5976 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ENVELOPED_DATA,
5977 cRecipientInfo), CRYPT_DecodeRecipientInfoArray,
5978 MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
5979 FALSE, TRUE, offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo), 0 },
5980 { ASN_SEQUENCEOF, offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo),
5981 CRYPT_AsnDecodeEncryptedContentInfo,
5982 sizeof(CRYPT_ENCRYPTED_CONTENT_INFO), FALSE, TRUE,
5983 offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo.contentType), 0 },
5986 TRACE("%p, %d, %08x, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags,
5987 pDecodePara, envelopedData, pcbEnvelopedData);
5989 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5990 pbEncoded, cbEncoded, dwFlags, pDecodePara, envelopedData,
5991 pcbEnvelopedData, NULL, NULL);
5992 TRACE("returning %d\n", ret);
5993 return ret;
5996 static BOOL WINAPI CRYPT_AsnDecodeObjectIdentifier(DWORD dwCertEncodingType,
5997 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5998 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6000 DWORD bytesNeeded = 0;
6001 BOOL ret;
6003 __TRY
6005 ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
6006 NULL, &bytesNeeded, NULL);
6007 if (ret)
6009 if (!pvStructInfo)
6010 *pcbStructInfo = bytesNeeded;
6011 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
6013 LPSTR *info;
6015 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6016 pvStructInfo = *(BYTE **)pvStructInfo;
6018 info = pvStructInfo;
6019 *info = (void *)((BYTE *)info + sizeof(*info));
6020 ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
6021 pvStructInfo, &bytesNeeded, NULL);
6022 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
6023 CRYPT_FreeSpace(pDecodePara, info);
6027 __EXCEPT_PAGE_FAULT
6029 SetLastError(STATUS_ACCESS_VIOLATION);
6030 ret = FALSE;
6032 __ENDTRY
6033 return ret;
6036 static BOOL WINAPI CRYPT_AsnDecodeEccSignature(DWORD dwCertEncodingType,
6037 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6038 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6040 BOOL ret;
6041 struct AsnDecodeSequenceItem items[] = {
6042 { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, r),
6043 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE,
6044 TRUE, offsetof(CERT_ECC_SIGNATURE, r.pbData), 0 },
6045 { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, s),
6046 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE,
6047 TRUE, offsetof(CERT_ECC_SIGNATURE, s.pbData), 0 },
6050 __TRY
6052 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6053 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6054 pcbStructInfo, NULL, NULL);
6056 __EXCEPT_PAGE_FAULT
6058 SetLastError(STATUS_ACCESS_VIOLATION);
6059 ret = FALSE;
6061 __ENDTRY
6062 return ret;
6065 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
6066 LPCSTR lpszStructType)
6068 CryptDecodeObjectExFunc decodeFunc = NULL;
6070 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
6071 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
6073 SetLastError(ERROR_FILE_NOT_FOUND);
6074 return NULL;
6076 if (IS_INTOID(lpszStructType))
6078 switch (LOWORD(lpszStructType))
6080 case LOWORD(X509_CERT):
6081 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
6082 break;
6083 case LOWORD(X509_CERT_TO_BE_SIGNED):
6084 decodeFunc = CRYPT_AsnDecodeCert;
6085 break;
6086 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
6087 decodeFunc = CRYPT_AsnDecodeCRL;
6088 break;
6089 case LOWORD(X509_EXTENSIONS):
6090 decodeFunc = CRYPT_AsnDecodeExtensions;
6091 break;
6092 case LOWORD(X509_NAME_VALUE):
6093 decodeFunc = CRYPT_AsnDecodeNameValue;
6094 break;
6095 case LOWORD(X509_NAME):
6096 decodeFunc = CRYPT_AsnDecodeName;
6097 break;
6098 case LOWORD(X509_PUBLIC_KEY_INFO):
6099 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
6100 break;
6101 case LOWORD(X509_AUTHORITY_KEY_ID):
6102 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
6103 break;
6104 case LOWORD(X509_ALTERNATE_NAME):
6105 decodeFunc = CRYPT_AsnDecodeAltName;
6106 break;
6107 case LOWORD(X509_BASIC_CONSTRAINTS):
6108 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
6109 break;
6110 case LOWORD(X509_BASIC_CONSTRAINTS2):
6111 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
6112 break;
6113 case LOWORD(X509_CERT_POLICIES):
6114 decodeFunc = CRYPT_AsnDecodeCertPolicies;
6115 break;
6116 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
6117 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
6118 break;
6119 case LOWORD(PKCS_RSA_PRIVATE_KEY):
6120 decodeFunc = CRYPT_AsnDecodeRsaPrivKey;
6121 break;
6122 case LOWORD(X509_UNICODE_NAME):
6123 decodeFunc = CRYPT_AsnDecodeUnicodeName;
6124 break;
6125 case LOWORD(PKCS_ATTRIBUTE):
6126 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
6127 break;
6128 case LOWORD(X509_UNICODE_NAME_VALUE):
6129 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
6130 break;
6131 case LOWORD(X509_OCTET_STRING):
6132 decodeFunc = CRYPT_AsnDecodeOctetString;
6133 break;
6134 case LOWORD(X509_BITS):
6135 case LOWORD(X509_KEY_USAGE):
6136 decodeFunc = CRYPT_AsnDecodeBits;
6137 break;
6138 case LOWORD(X509_INTEGER):
6139 decodeFunc = CRYPT_AsnDecodeInt;
6140 break;
6141 case LOWORD(X509_MULTI_BYTE_INTEGER):
6142 decodeFunc = CRYPT_AsnDecodeInteger;
6143 break;
6144 case LOWORD(X509_MULTI_BYTE_UINT):
6145 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
6146 break;
6147 case LOWORD(X509_ENUMERATED):
6148 decodeFunc = CRYPT_AsnDecodeEnumerated;
6149 break;
6150 case LOWORD(X509_CHOICE_OF_TIME):
6151 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
6152 break;
6153 case LOWORD(X509_AUTHORITY_KEY_ID2):
6154 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
6155 break;
6156 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
6157 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
6158 break;
6159 case LOWORD(PKCS_CONTENT_INFO):
6160 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
6161 break;
6162 case LOWORD(X509_SEQUENCE_OF_ANY):
6163 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
6164 break;
6165 case LOWORD(PKCS_UTC_TIME):
6166 decodeFunc = CRYPT_AsnDecodeUtcTime;
6167 break;
6168 case LOWORD(X509_CRL_DIST_POINTS):
6169 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
6170 break;
6171 case LOWORD(X509_ENHANCED_KEY_USAGE):
6172 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
6173 break;
6174 case LOWORD(PKCS_CTL):
6175 decodeFunc = CRYPT_AsnDecodeCTL;
6176 break;
6177 case LOWORD(PKCS_SMIME_CAPABILITIES):
6178 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
6179 break;
6180 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
6181 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
6182 break;
6183 case LOWORD(PKCS_ATTRIBUTES):
6184 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
6185 break;
6186 case LOWORD(X509_ISSUING_DIST_POINT):
6187 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
6188 break;
6189 case LOWORD(X509_NAME_CONSTRAINTS):
6190 decodeFunc = CRYPT_AsnDecodeNameConstraints;
6191 break;
6192 case LOWORD(X509_POLICY_MAPPINGS):
6193 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6194 break;
6195 case LOWORD(X509_POLICY_CONSTRAINTS):
6196 decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
6197 break;
6198 case LOWORD(PKCS7_SIGNER_INFO):
6199 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
6200 break;
6201 case LOWORD(CMS_SIGNER_INFO):
6202 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
6203 break;
6204 case LOWORD(X509_OBJECT_IDENTIFIER):
6205 decodeFunc = CRYPT_AsnDecodeObjectIdentifier;
6206 break;
6207 case LOWORD(X509_ECC_SIGNATURE):
6208 decodeFunc = CRYPT_AsnDecodeEccSignature;
6209 break;
6212 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
6213 decodeFunc = CRYPT_AsnDecodeExtensions;
6214 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
6215 decodeFunc = CRYPT_AsnDecodeUtcTime;
6216 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
6217 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
6218 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
6219 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
6220 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
6221 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6222 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
6223 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
6224 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
6225 decodeFunc = CRYPT_AsnDecodeEnumerated;
6226 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
6227 decodeFunc = CRYPT_AsnDecodeBits;
6228 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
6229 decodeFunc = CRYPT_AsnDecodeOctetString;
6230 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
6231 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
6232 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
6233 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
6234 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
6235 decodeFunc = CRYPT_AsnDecodeAltName;
6236 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
6237 decodeFunc = CRYPT_AsnDecodeAltName;
6238 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
6239 decodeFunc = CRYPT_AsnDecodeAltName;
6240 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
6241 decodeFunc = CRYPT_AsnDecodeAltName;
6242 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
6243 decodeFunc = CRYPT_AsnDecodeAltName;
6244 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
6245 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
6246 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
6247 decodeFunc = CRYPT_AsnDecodeCertPolicies;
6248 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
6249 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6250 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
6251 decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
6252 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
6253 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
6254 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
6255 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
6256 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
6257 decodeFunc = CRYPT_AsnDecodeNameConstraints;
6258 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
6259 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
6260 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
6261 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
6262 else if (!strcmp(lpszStructType, szOID_CTL))
6263 decodeFunc = CRYPT_AsnDecodeCTL;
6264 else if (!strcmp(lpszStructType, szOID_ECC_PUBLIC_KEY))
6265 decodeFunc = CRYPT_AsnDecodeObjectIdentifier;
6266 return decodeFunc;
6269 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
6270 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
6272 static HCRYPTOIDFUNCSET set = NULL;
6273 CryptDecodeObjectFunc decodeFunc = NULL;
6275 if (!set)
6276 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
6277 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
6278 (void **)&decodeFunc, hFunc);
6279 return decodeFunc;
6282 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
6283 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
6285 static HCRYPTOIDFUNCSET set = NULL;
6286 CryptDecodeObjectExFunc decodeFunc = NULL;
6288 if (!set)
6289 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
6290 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
6291 (void **)&decodeFunc, hFunc);
6292 return decodeFunc;
6295 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
6296 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
6297 DWORD *pcbStructInfo)
6299 return CryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
6300 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
6303 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
6304 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6305 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6307 BOOL ret = FALSE;
6308 CryptDecodeObjectExFunc decodeFunc;
6309 HCRYPTOIDFUNCADDR hFunc = NULL;
6311 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
6312 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
6313 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
6315 if (!pvStructInfo && !pcbStructInfo)
6317 SetLastError(ERROR_INVALID_PARAMETER);
6318 return FALSE;
6320 if (cbEncoded > MAX_ENCODED_LEN)
6322 SetLastError(CRYPT_E_ASN1_LARGE);
6323 return FALSE;
6326 SetLastError(NOERROR);
6327 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6329 if (!pvStructInfo)
6331 SetLastError(ERROR_INVALID_PARAMETER);
6332 return FALSE;
6334 *(BYTE **)pvStructInfo = NULL;
6336 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
6337 if (!decodeFunc)
6339 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
6340 debugstr_a(lpszStructType));
6341 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
6342 &hFunc);
6344 if (decodeFunc)
6345 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
6346 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
6347 else
6349 CryptDecodeObjectFunc pCryptDecodeObject =
6350 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
6352 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
6353 * directly, as that could cause an infinite loop.
6355 if (pCryptDecodeObject)
6357 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6359 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
6360 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
6361 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
6362 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
6364 ret = pCryptDecodeObject(dwCertEncodingType,
6365 lpszStructType, pbEncoded, cbEncoded, dwFlags,
6366 *(BYTE **)pvStructInfo, pcbStructInfo);
6367 if (!ret)
6368 CRYPT_FreeSpace(pDecodePara, *(BYTE **)pvStructInfo);
6371 else
6372 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
6373 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
6376 if (hFunc)
6377 CryptFreeOIDFunctionAddress(hFunc, 0);
6378 TRACE_(crypt)("returning %d\n", ret);
6379 return ret;
6382 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
6384 BOOL ret;
6386 TRACE_(crypt)("(%p)\n", pPFX);
6388 /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
6389 * version integer of length 1 (3 encoded byes) and at least one other
6390 * datum (two encoded bytes), plus at least two bytes for the outer
6391 * sequence. Thus, even an empty PFX blob is at least 7 bytes in length.
6393 if (pPFX->cbData < 7)
6394 ret = FALSE;
6395 else if (pPFX->pbData[0] == ASN_SEQUENCE)
6397 DWORD len;
6399 if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
6401 BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
6403 /* Need at least three bytes for the integer version */
6404 if (pPFX->cbData < 1 + lenLen + 3)
6405 ret = FALSE;
6406 else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
6407 pPFX->pbData[1 + lenLen + 1] != 1 || /* Definite length */
6408 pPFX->pbData[1 + lenLen + 2] != 3) /* PFX version */
6409 ret = FALSE;
6412 else
6413 ret = FALSE;
6414 return ret;