crypt32: Let CRYPT_AsnDecodeArray allocate memory for its callers.
[wine/hacks.git] / dlls / crypt32 / decode.c
blobbeb33f18e537ed19f34ae59de75d9d7cb28ddd9b
1 /*
2 * Copyright 2005-2009 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
33 #include "config.h"
34 #include "wine/port.h"
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
41 #define NONAMELESSUNION
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "winnls.h"
47 #include "snmp.h"
48 #include "wine/debug.h"
49 #include "wine/exception.h"
50 #include "crypt32_private.h"
52 /* This is a bit arbitrary, but to set some limit: */
53 #define MAX_ENCODED_LEN 0x02000000
55 #define ASN_FLAGS_MASK 0xe0
56 #define ASN_TYPE_MASK 0x1f
58 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
59 WINE_DECLARE_DEBUG_CHANNEL(crypt);
61 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
62 DWORD, DWORD, void *, DWORD *);
63 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
64 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
66 /* Internal decoders don't do memory allocation or exception handling, and
67 * they report how many bytes they decoded.
69 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
70 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
72 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
73 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
74 DWORD *pcbDecoded);
75 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
76 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
77 DWORD *pcbDecoded);
78 /* Assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set ahead of time.
80 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
81 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
82 /* Assumes algo->Parameters.pbData is set ahead of time. */
83 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
84 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
85 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
86 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
87 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
88 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
89 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
90 DWORD *pcbDecoded);
91 /* Doesn't check the tag, assumes the caller does so */
92 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
93 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
94 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
95 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
96 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
97 * member has been initialized, doesn't do exception handling, and doesn't do
98 * memory allocation. Also doesn't check tag, assumes the caller has checked
99 * it.
101 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
102 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
103 DWORD *pcbDecoded);
104 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
105 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
106 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
107 DWORD *pcbDecoded);
108 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
109 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
110 DWORD *pcbDecoded);
112 /* Gets the number of length bytes from the given (leading) length byte */
113 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
115 /* Helper function to get the encoded length of the data starting at pbEncoded,
116 * where pbEncoded[0] is the tag. If the data are too short to contain a
117 * length or if the length is too large for cbEncoded, sets an appropriate
118 * error code and returns FALSE. If the encoded length is unknown due to
119 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
121 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
122 DWORD *len)
124 BOOL ret;
126 if (cbEncoded <= 1)
128 SetLastError(CRYPT_E_ASN1_CORRUPT);
129 ret = FALSE;
131 else if (pbEncoded[1] <= 0x7f)
133 if (pbEncoded[1] + 1 > cbEncoded)
135 SetLastError(CRYPT_E_ASN1_EOD);
136 ret = FALSE;
138 else
140 *len = pbEncoded[1];
141 ret = TRUE;
144 else if (pbEncoded[1] == 0x80)
146 *len = CMSG_INDEFINITE_LENGTH;
147 ret = TRUE;
149 else
151 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
153 if (lenLen > sizeof(DWORD) + 1)
155 SetLastError(CRYPT_E_ASN1_LARGE);
156 ret = FALSE;
158 else if (lenLen + 2 > cbEncoded)
160 SetLastError(CRYPT_E_ASN1_CORRUPT);
161 ret = FALSE;
163 else
165 DWORD out = 0;
167 pbEncoded += 2;
168 while (--lenLen)
170 out <<= 8;
171 out |= *pbEncoded++;
173 if (out + lenLen + 1 > cbEncoded)
175 SetLastError(CRYPT_E_ASN1_EOD);
176 ret = FALSE;
178 else
180 *len = out;
181 ret = TRUE;
185 return ret;
188 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
189 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
191 BOOL ret;
193 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
194 *len == CMSG_INDEFINITE_LENGTH)
196 SetLastError(CRYPT_E_ASN1_CORRUPT);
197 ret = FALSE;
199 return ret;
202 /* Helper function to check *pcbStructInfo, set it to the required size, and
203 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
204 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
205 * pointer to the newly allocated memory.
207 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
208 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
209 DWORD bytesNeeded)
211 BOOL ret = TRUE;
213 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
215 if (pDecodePara && pDecodePara->pfnAlloc)
216 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
217 else
218 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
219 if (!*(BYTE **)pvStructInfo)
220 ret = FALSE;
221 else
222 *pcbStructInfo = bytesNeeded;
224 else if (*pcbStructInfo < bytesNeeded)
226 *pcbStructInfo = bytesNeeded;
227 SetLastError(ERROR_MORE_DATA);
228 ret = FALSE;
230 else
231 *pcbStructInfo = bytesNeeded;
232 return ret;
235 static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
237 if (pDecodePara && pDecodePara->pfnFree)
238 pDecodePara->pfnFree(pv);
239 else
240 LocalFree(pv);
243 /* Helper function to check *pcbStructInfo and set it to the required size.
244 * Assumes pvStructInfo is not NULL.
246 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
248 BOOL ret;
250 if (*pcbStructInfo < bytesNeeded)
252 *pcbStructInfo = bytesNeeded;
253 SetLastError(ERROR_MORE_DATA);
254 ret = FALSE;
256 else
258 *pcbStructInfo = bytesNeeded;
259 ret = TRUE;
261 return ret;
264 /* tag:
265 * The expected tag of the item. If tag is 0, decodeFunc is called
266 * regardless of the tag value seen.
267 * offset:
268 * A sequence is decoded into a struct. The offset member is the
269 * offset of this item within that struct.
270 * decodeFunc:
271 * The decoder function to use. If this is NULL, then the member isn't
272 * decoded, but minSize space is reserved for it.
273 * minSize:
274 * The minimum amount of space occupied after decoding. You must set this.
275 * optional:
276 * If true, and the tag doesn't match the expected tag for this item,
277 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
278 * filled with 0 for this member.
279 * hasPointer, pointerOffset:
280 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
281 * the offset within the struct of the data pointer (or to the
282 * first data pointer, if more than one exist).
283 * size:
284 * Used by CRYPT_AsnDecodeSequence, not for your use.
286 struct AsnDecodeSequenceItem
288 BYTE tag;
289 DWORD offset;
290 InternalDecodeFunc decodeFunc;
291 DWORD minSize;
292 BOOL optional;
293 BOOL hasPointer;
294 DWORD pointerOffset;
295 DWORD size;
298 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
299 #define MEMBERSIZE(s, member, nextmember) \
300 (offsetof(s, nextmember) - offsetof(s, member))
302 /* Decodes the items in a sequence, where the items are described in items,
303 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
304 * pvStructInfo. nextData is a pointer to the memory location at which the
305 * first decoded item with a dynamic pointer should point.
306 * Upon decoding, *cbDecoded is the total number of bytes decoded.
307 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
309 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
310 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
311 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
313 BOOL ret;
314 DWORD i, decoded = 0;
315 const BYTE *ptr = pbEncoded;
317 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
318 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
320 for (i = 0, ret = TRUE; ret && i < cItem; i++)
322 if (cbEncoded - (ptr - pbEncoded) != 0)
324 DWORD itemLen;
326 if ((ret = CRYPT_GetLengthIndefinite(ptr,
327 cbEncoded - (ptr - pbEncoded), &itemLen)))
329 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
331 if (ptr[0] == items[i].tag || !items[i].tag)
333 DWORD itemEncodedLen;
335 if (itemLen == CMSG_INDEFINITE_LENGTH)
336 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
337 else
338 itemEncodedLen = 1 + itemLenBytes + itemLen;
339 if (nextData && pvStructInfo && items[i].hasPointer)
341 TRACE("Setting next pointer to %p\n",
342 nextData);
343 *(BYTE **)((BYTE *)pvStructInfo +
344 items[i].pointerOffset) = nextData;
346 if (items[i].decodeFunc)
348 DWORD itemDecoded;
350 if (pvStructInfo)
351 TRACE("decoding item %d\n", i);
352 else
353 TRACE("sizing item %d\n", i);
354 ret = items[i].decodeFunc(ptr, itemEncodedLen,
355 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
356 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
357 : NULL, &items[i].size, &itemDecoded);
358 if (ret)
360 /* Account for alignment padding */
361 items[i].size = ALIGN_DWORD_PTR(items[i].size);
362 TRACE("item %d size: %d\n", i, items[i].size);
363 if (nextData && items[i].hasPointer &&
364 items[i].size > items[i].minSize)
365 nextData += items[i].size - items[i].minSize;
366 if (itemDecoded > itemEncodedLen)
368 WARN("decoded length %d exceeds encoded %d\n",
369 itemDecoded, itemEncodedLen);
370 SetLastError(CRYPT_E_ASN1_CORRUPT);
371 ret = FALSE;
373 else
375 ptr += itemDecoded;
376 decoded += itemDecoded;
377 TRACE("item %d: decoded %d bytes\n", i,
378 itemDecoded);
381 else if (items[i].optional &&
382 GetLastError() == CRYPT_E_ASN1_BADTAG)
384 TRACE("skipping optional item %d\n", i);
385 items[i].size = items[i].minSize;
386 SetLastError(NOERROR);
387 ret = TRUE;
389 else
390 TRACE("item %d failed: %08x\n", i,
391 GetLastError());
393 else if (itemLen == CMSG_INDEFINITE_LENGTH)
395 ERR("can't use indefinite length encoding without a decoder\n");
396 SetLastError(CRYPT_E_ASN1_CORRUPT);
397 ret = FALSE;
399 else
401 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
402 ptr += itemEncodedLen;
403 decoded += itemEncodedLen;
404 items[i].size = items[i].minSize;
407 else if (items[i].optional)
409 TRACE("skipping optional item %d\n", i);
410 items[i].size = items[i].minSize;
412 else
414 TRACE("item %d: tag %02x doesn't match expected %02x\n",
415 i, ptr[0], items[i].tag);
416 SetLastError(CRYPT_E_ASN1_BADTAG);
417 ret = FALSE;
421 else if (items[i].optional)
423 TRACE("missing optional item %d, skipping\n", i);
424 items[i].size = items[i].minSize;
426 else
428 TRACE("not enough bytes for item %d, failing\n", i);
429 SetLastError(CRYPT_E_ASN1_CORRUPT);
430 ret = FALSE;
433 if (cbDecoded)
434 *cbDecoded = decoded;
435 TRACE("returning %d\n", ret);
436 return ret;
439 /* This decodes an arbitrary sequence into a contiguous block of memory
440 * (basically, a struct.) Each element being decoded is described by a struct
441 * AsnDecodeSequenceItem, see above.
442 * startingPointer is an optional pointer to the first place where dynamic
443 * data will be stored. If you know the starting offset, you may pass it
444 * here. Otherwise, pass NULL, and one will be inferred from the items.
446 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
447 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
448 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
449 DWORD *pcbDecoded, void *startingPointer)
451 BOOL ret;
453 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
454 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
455 startingPointer);
457 if (!cbEncoded)
459 SetLastError(CRYPT_E_ASN1_EOD);
460 return FALSE;
462 if (pbEncoded[0] == ASN_SEQUENCE)
464 DWORD dataLen;
466 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
468 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
469 const BYTE *ptr = pbEncoded + 1 + lenBytes;
470 BOOL indefinite = FALSE;
472 cbEncoded -= 1 + lenBytes;
473 if (dataLen == CMSG_INDEFINITE_LENGTH)
475 dataLen = cbEncoded;
476 indefinite = TRUE;
478 else if (cbEncoded < dataLen)
480 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
481 cbEncoded);
482 SetLastError(CRYPT_E_ASN1_CORRUPT);
483 ret = FALSE;
485 if (ret)
487 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
488 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
489 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
491 if (cbDecoded > cbEncoded - 2)
493 /* Not enough space for 0 TLV */
494 SetLastError(CRYPT_E_ASN1_CORRUPT);
495 ret = FALSE;
497 else if (*(ptr + cbDecoded) != 0 ||
498 *(ptr + cbDecoded + 1) != 0)
500 TRACE("expected 0 TLV\n");
501 SetLastError(CRYPT_E_ASN1_CORRUPT);
502 ret = FALSE;
504 else
505 cbDecoded += 2;
508 if (ret && !indefinite && cbDecoded != dataLen)
510 TRACE("expected %d decoded, got %d, failing\n", dataLen,
511 cbDecoded);
512 SetLastError(CRYPT_E_ASN1_CORRUPT);
513 ret = FALSE;
515 if (ret)
517 DWORD i, bytesNeeded = 0, structSize = 0;
519 for (i = 0; i < cItem; i++)
521 bytesNeeded += items[i].size;
522 structSize = max( structSize, items[i].offset + items[i].minSize );
524 if (pcbDecoded)
525 *pcbDecoded = 1 + lenBytes + cbDecoded;
526 if (!pvStructInfo)
527 *pcbStructInfo = bytesNeeded;
528 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
529 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
531 BYTE *nextData;
533 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
534 pvStructInfo = *(BYTE **)pvStructInfo;
535 if (startingPointer)
536 nextData = startingPointer;
537 else
538 nextData = (BYTE *)pvStructInfo + structSize;
539 memset(pvStructInfo, 0, structSize);
540 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
541 ptr, dataLen, dwFlags, pvStructInfo, nextData,
542 &cbDecoded);
543 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
544 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
549 else
551 SetLastError(CRYPT_E_ASN1_BADTAG);
552 ret = FALSE;
554 TRACE("returning %d (%08x)\n", ret, GetLastError());
555 return ret;
558 /* tag:
559 * The expected tag of the entire encoded array (usually a variant
560 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
561 * regardless of the tag seen.
562 * countOffset:
563 * The offset within the outer structure at which the count exists.
564 * For example, a structure such as CRYPT_ATTRIBUTES has countOffset == 0,
565 * while CRYPT_ATTRIBUTE has countOffset ==
566 * offsetof(CRYPT_ATTRIBUTE, cValue).
567 * arrayOffset:
568 * The offset within the outer structure at which the array pointer exists.
569 * For example, CRYPT_ATTRIBUTES has arrayOffset ==
570 * offsetof(CRYPT_ATTRIBUTES, rgAttr).
571 * minArraySize:
572 * The minimum size of the decoded array. On WIN32, this is always 8:
573 * sizeof(DWORD) + sizeof(void *). On WIN64, it can be larger due to
574 * alignment.
575 * decodeFunc:
576 * used to decode each item in the array
577 * itemSize:
578 * is the minimum size of each decoded item
579 * hasPointer:
580 * indicates whether each item has a dynamic pointer
581 * pointerOffset:
582 * indicates the offset within itemSize at which the pointer exists
584 struct AsnArrayDescriptor
586 BYTE tag;
587 DWORD countOffset;
588 DWORD arrayOffset;
589 DWORD minArraySize;
590 InternalDecodeFunc decodeFunc;
591 DWORD itemSize;
592 BOOL hasPointer;
593 DWORD pointerOffset;
596 struct AsnArrayItemSize
598 DWORD encodedLen;
599 DWORD size;
602 /* Decodes an array of like types into a structure described by a struct
603 * AsnArrayDescriptor.
605 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
606 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
607 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
608 DWORD *pcbDecoded)
610 BOOL ret = TRUE;
612 TRACE("%p, %p, %d, %p, %d\n", arrayDesc, pbEncoded,
613 cbEncoded, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
615 if (!cbEncoded)
617 SetLastError(CRYPT_E_ASN1_EOD);
618 ret = FALSE;
620 else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
622 DWORD dataLen;
624 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
626 DWORD bytesNeeded = arrayDesc->minArraySize, cItems = 0, decoded;
627 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
628 /* There can be arbitrarily many items, but there is often only one.
630 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
632 decoded = 1 + lenBytes;
633 if (dataLen)
635 const BYTE *ptr;
636 BOOL doneDecoding = FALSE;
638 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
640 if (dataLen == CMSG_INDEFINITE_LENGTH)
642 if (ptr[0] == 0)
644 doneDecoding = TRUE;
645 if (ptr[1] != 0)
647 SetLastError(CRYPT_E_ASN1_CORRUPT);
648 ret = FALSE;
650 else
651 decoded += 2;
654 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
655 doneDecoding = TRUE;
656 if (!doneDecoding)
658 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
660 /* Each item decoded may not tolerate extraneous bytes,
661 * so get the length of the next element if known.
663 if ((ret = CRYPT_GetLengthIndefinite(ptr,
664 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
666 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
667 itemEncoded = cbEncoded - (ptr - pbEncoded);
668 else
669 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
670 itemDataLen;
672 if (ret)
673 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
674 dwFlags, NULL, &size, &itemDecoded);
675 if (ret)
677 cItems++;
678 if (itemSizes != &itemSize)
679 itemSizes = CryptMemRealloc(itemSizes,
680 cItems * sizeof(struct AsnArrayItemSize));
681 else if (cItems > 1)
683 itemSizes =
684 CryptMemAlloc(
685 cItems * sizeof(struct AsnArrayItemSize));
686 if (itemSizes)
687 memcpy(itemSizes, &itemSize,
688 sizeof(itemSize));
690 if (itemSizes)
692 decoded += itemDecoded;
693 itemSizes[cItems - 1].encodedLen = itemEncoded;
694 itemSizes[cItems - 1].size = size;
695 bytesNeeded += size;
696 ptr += itemEncoded;
698 else
699 ret = FALSE;
704 if (ret)
706 if (pcbDecoded)
707 *pcbDecoded = decoded;
708 if (!pvStructInfo)
709 *pcbStructInfo = bytesNeeded;
710 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
711 pvStructInfo, pcbStructInfo, bytesNeeded)))
713 DWORD i, *pcItems;
714 BYTE *nextData;
715 const BYTE *ptr;
716 void *rgItems;
718 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
719 pvStructInfo = *(void **)pvStructInfo;
720 pcItems = pvStructInfo;
721 *pcItems = cItems;
722 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
724 rgItems = (BYTE *)pvStructInfo +
725 arrayDesc->minArraySize;
726 *(void **)((BYTE *)pcItems -
727 arrayDesc->countOffset + arrayDesc->arrayOffset) =
728 rgItems;
730 else
731 rgItems = *(void **)((BYTE *)pcItems -
732 arrayDesc->countOffset + arrayDesc->arrayOffset);
733 nextData = (BYTE *)rgItems + cItems * arrayDesc->itemSize;
734 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
735 i < cItems && ptr - pbEncoded - 1 - lenBytes <
736 dataLen; i++)
738 DWORD itemDecoded;
740 if (arrayDesc->hasPointer)
741 *(BYTE **)((BYTE *)rgItems + i * arrayDesc->itemSize
742 + arrayDesc->pointerOffset) = nextData;
743 ret = arrayDesc->decodeFunc(ptr,
744 itemSizes[i].encodedLen, 0,
745 (BYTE *)rgItems + i * arrayDesc->itemSize,
746 &itemSizes[i].size, &itemDecoded);
747 if (ret)
749 nextData += itemSizes[i].size - arrayDesc->itemSize;
750 ptr += itemDecoded;
755 if (itemSizes != &itemSize)
756 CryptMemFree(itemSizes);
759 else
761 SetLastError(CRYPT_E_ASN1_BADTAG);
762 ret = FALSE;
764 return ret;
767 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
768 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
769 * to CRYPT_E_ASN1_CORRUPT.
770 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
771 * set!
773 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
774 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
776 BOOL ret;
777 DWORD dataLen;
779 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
781 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
782 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
784 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
785 bytesNeeded += 1 + lenBytes + dataLen;
787 if (pcbDecoded)
788 *pcbDecoded = 1 + lenBytes + dataLen;
789 if (!pvStructInfo)
790 *pcbStructInfo = bytesNeeded;
791 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
793 CRYPT_DER_BLOB *blob;
795 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
796 pvStructInfo = *(BYTE **)pvStructInfo;
797 blob = pvStructInfo;
798 blob->cbData = 1 + lenBytes + dataLen;
799 if (blob->cbData)
801 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
802 blob->pbData = (BYTE *)pbEncoded;
803 else
805 assert(blob->pbData);
806 memcpy(blob->pbData, pbEncoded, blob->cbData);
809 else
811 SetLastError(CRYPT_E_ASN1_CORRUPT);
812 ret = FALSE;
816 return ret;
819 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
820 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
821 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
822 DWORD *pcbDecoded)
824 BOOL ret;
826 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
827 pvStructInfo, *pcbStructInfo, pcbDecoded);
829 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
830 * place.
832 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
833 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
834 pcbDecoded);
835 if (ret && pvStructInfo)
837 CRYPT_BIT_BLOB *blob = pvStructInfo;
839 if (blob->cbData)
841 DWORD i;
842 BYTE temp;
844 for (i = 0; i < blob->cbData / 2; i++)
846 temp = blob->pbData[i];
847 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
848 blob->pbData[blob->cbData - i - 1] = temp;
852 TRACE("returning %d (%08x)\n", ret, GetLastError());
853 return ret;
856 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
857 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
858 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
860 BOOL ret = TRUE;
862 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
863 pDecodePara, pvStructInfo, *pcbStructInfo);
865 __TRY
867 struct AsnDecodeSequenceItem items[] = {
868 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
869 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
870 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
871 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
872 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
873 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
874 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
875 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
876 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
877 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
880 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
881 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
882 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
883 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
884 pcbStructInfo, NULL, NULL);
886 __EXCEPT_PAGE_FAULT
888 SetLastError(STATUS_ACCESS_VIOLATION);
889 ret = FALSE;
891 __ENDTRY
893 TRACE("Returning %d (%08x)\n", ret, GetLastError());
894 return ret;
897 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
898 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
900 BOOL ret;
901 DWORD dataLen;
903 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
905 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
907 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
908 dwFlags, pvStructInfo, pcbStructInfo, NULL);
909 if (pcbDecoded)
910 *pcbDecoded = 1 + lenBytes + dataLen;
912 return ret;
915 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
916 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
918 BOOL ret;
920 struct AsnDecodeSequenceItem items[] = {
921 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
922 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
923 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
924 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
927 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
928 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
929 pcbDecoded, NULL);
930 return ret;
933 static BOOL CRYPT_AsnDecodeCertExtensionsInternal(const BYTE *pbEncoded,
934 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
935 DWORD *pcbDecoded)
937 BOOL ret = TRUE;
938 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
939 offsetof(CERT_INFO, cExtension), offsetof(CERT_INFO, rgExtension),
940 FINALMEMBERSIZE(CERT_INFO, cExtension),
941 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
942 offsetof(CERT_EXTENSION, pszObjId) };
944 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
945 pvStructInfo, *pcbStructInfo, pcbDecoded);
947 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
948 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
949 return ret;
952 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
953 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
954 DWORD *pcbDecoded)
956 BOOL ret;
957 DWORD dataLen;
959 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
961 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
963 ret = CRYPT_AsnDecodeCertExtensionsInternal(pbEncoded + 1 + lenBytes,
964 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
965 if (ret && pcbDecoded)
966 *pcbDecoded = 1 + lenBytes + dataLen;
968 return ret;
971 static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
972 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
973 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
975 BOOL ret = TRUE;
976 struct AsnDecodeSequenceItem items[] = {
977 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
978 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
979 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
980 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
981 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
982 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
983 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
984 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
985 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
986 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
987 Issuer.pbData) },
988 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
989 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
990 FALSE, 0 },
991 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
992 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
993 Subject.pbData) },
994 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
995 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
996 FALSE, TRUE, offsetof(CERT_INFO,
997 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
998 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
999 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1000 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
1001 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
1002 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1003 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
1004 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
1005 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(CERT_INFO, cExtension),
1006 TRUE, TRUE, offsetof(CERT_INFO, rgExtension), 0 },
1009 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1010 pDecodePara, pvStructInfo, *pcbStructInfo);
1012 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1013 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1014 NULL, NULL);
1015 if (ret && pvStructInfo)
1017 CERT_INFO *info;
1019 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1020 info = *(CERT_INFO **)pvStructInfo;
1021 else
1022 info = pvStructInfo;
1023 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1024 !info->Subject.cbData)
1026 SetLastError(CRYPT_E_ASN1_CORRUPT);
1027 /* Don't need to deallocate, because it should have failed on the
1028 * first pass (and no memory was allocated.)
1030 ret = FALSE;
1034 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1035 return ret;
1038 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1039 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1040 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1042 BOOL ret = FALSE;
1044 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1045 pDecodePara, pvStructInfo, *pcbStructInfo);
1047 __TRY
1049 DWORD size = 0;
1051 /* Unless told not to, first try to decode it as a signed cert. */
1052 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1054 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1056 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1057 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1058 &signedCert, &size);
1059 if (ret)
1061 size = 0;
1062 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1063 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1064 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1065 pvStructInfo, pcbStructInfo);
1066 LocalFree(signedCert);
1069 /* Failing that, try it as an unsigned cert */
1070 if (!ret)
1072 size = 0;
1073 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1074 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1075 pDecodePara, pvStructInfo, pcbStructInfo);
1078 __EXCEPT_PAGE_FAULT
1080 SetLastError(STATUS_ACCESS_VIOLATION);
1082 __ENDTRY
1084 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1085 return ret;
1088 static BOOL CRYPT_AsnDecodeCRLEntryExtensions(const BYTE *pbEncoded,
1089 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1090 DWORD *pcbDecoded)
1092 BOOL ret = TRUE;
1093 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1094 offsetof(CRL_ENTRY, cExtension), offsetof(CRL_ENTRY, rgExtension),
1095 FINALMEMBERSIZE(CRL_ENTRY, cExtension),
1096 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1097 offsetof(CERT_EXTENSION, pszObjId) };
1099 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1100 pvStructInfo, *pcbStructInfo, pcbDecoded);
1102 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1103 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1104 return ret;
1107 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1108 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1110 BOOL ret;
1111 struct AsnDecodeSequenceItem items[] = {
1112 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1113 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1114 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1115 { 0, offsetof(CRL_ENTRY, RevocationDate),
1116 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1117 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1118 CRYPT_AsnDecodeCRLEntryExtensions,
1119 FINALMEMBERSIZE(CRL_ENTRY, cExtension), TRUE, TRUE,
1120 offsetof(CRL_ENTRY, rgExtension), 0 },
1122 PCRL_ENTRY entry = pvStructInfo;
1124 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1125 *pcbStructInfo);
1127 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1128 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1129 entry ? entry->SerialNumber.pbData : NULL);
1130 if (ret && entry && !entry->SerialNumber.cbData)
1132 WARN("empty CRL entry serial number\n");
1133 SetLastError(CRYPT_E_ASN1_CORRUPT);
1134 ret = FALSE;
1136 return ret;
1139 /* Warning: assumes pvStructInfo points to the cCRLEntry member of a CRL_INFO
1140 * whose rgCRLEntry member has been set prior to calling.
1142 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1143 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1145 BOOL ret;
1146 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1147 offsetof(CRL_INFO, cCRLEntry), offsetof(CRL_INFO, rgCRLEntry),
1148 MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1149 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1150 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1152 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1153 pvStructInfo, *pcbStructInfo, pcbDecoded);
1155 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1156 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1157 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1158 return ret;
1161 static BOOL CRYPT_AsnDecodeCRLExtensionsInternal(const BYTE *pbEncoded,
1162 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1163 DWORD *pcbDecoded)
1165 BOOL ret = TRUE;
1166 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1167 offsetof(CRL_INFO, cExtension), offsetof(CRL_INFO, rgExtension),
1168 FINALMEMBERSIZE(CRL_INFO, cExtension),
1169 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1170 offsetof(CERT_EXTENSION, pszObjId) };
1172 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1173 pvStructInfo, *pcbStructInfo, pcbDecoded);
1175 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1176 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1177 return ret;
1180 static BOOL CRYPT_AsnDecodeCRLExtensions(const BYTE *pbEncoded,
1181 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1182 DWORD *pcbDecoded)
1184 BOOL ret;
1185 DWORD dataLen;
1187 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1189 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1191 ret = CRYPT_AsnDecodeCRLExtensionsInternal(pbEncoded + 1 + lenBytes,
1192 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
1193 if (ret && pcbDecoded)
1194 *pcbDecoded = 1 + lenBytes + dataLen;
1196 return ret;
1199 static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1200 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1201 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1203 struct AsnDecodeSequenceItem items[] = {
1204 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1205 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1206 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1207 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1208 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1209 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1210 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1211 Issuer.pbData) },
1212 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1213 sizeof(FILETIME), FALSE, FALSE, 0 },
1214 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1215 sizeof(FILETIME), TRUE, FALSE, 0 },
1216 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1217 CRYPT_AsnDecodeCRLEntries, MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1218 TRUE, TRUE, offsetof(CRL_INFO, rgCRLEntry), 0 },
1219 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1220 CRYPT_AsnDecodeCRLExtensions, FINALMEMBERSIZE(CRL_INFO, cExtension),
1221 TRUE, TRUE, offsetof(CRL_INFO, rgExtension), 0 },
1223 BOOL ret = TRUE;
1225 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1226 pDecodePara, pvStructInfo, *pcbStructInfo);
1228 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1229 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1230 NULL, NULL);
1232 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1233 return ret;
1236 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1237 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1238 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1240 BOOL ret = FALSE;
1242 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1243 pDecodePara, pvStructInfo, *pcbStructInfo);
1245 __TRY
1247 DWORD size = 0;
1249 /* Unless told not to, first try to decode it as a signed crl. */
1250 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1252 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1254 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1255 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1256 &signedCrl, &size);
1257 if (ret)
1259 size = 0;
1260 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1261 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1262 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1263 pvStructInfo, pcbStructInfo);
1264 LocalFree(signedCrl);
1267 /* Failing that, try it as an unsigned crl */
1268 if (!ret)
1270 size = 0;
1271 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1272 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1273 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1276 __EXCEPT_PAGE_FAULT
1278 SetLastError(STATUS_ACCESS_VIOLATION);
1280 __ENDTRY
1282 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1283 return ret;
1286 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1287 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1289 BOOL ret = TRUE;
1290 DWORD dataLen;
1292 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1293 pvStructInfo, *pcbStructInfo);
1295 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1297 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1298 DWORD bytesNeeded = sizeof(LPSTR);
1300 if (dataLen)
1302 /* The largest possible string for the first two components
1303 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1305 char firstTwo[6];
1306 const BYTE *ptr;
1308 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1309 pbEncoded[1 + lenBytes] / 40,
1310 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1311 * 40);
1312 bytesNeeded += strlen(firstTwo) + 1;
1313 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1314 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1316 /* large enough for ".4000000" */
1317 char str[9];
1318 int val = 0;
1320 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1321 (*ptr & 0x80))
1323 val <<= 7;
1324 val |= *ptr & 0x7f;
1325 ptr++;
1327 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1328 (*ptr & 0x80))
1330 SetLastError(CRYPT_E_ASN1_CORRUPT);
1331 ret = FALSE;
1333 else
1335 val <<= 7;
1336 val |= *ptr++;
1337 snprintf(str, sizeof(str), ".%d", val);
1338 bytesNeeded += strlen(str);
1342 if (pcbDecoded)
1343 *pcbDecoded = 1 + lenBytes + dataLen;
1344 if (!pvStructInfo)
1345 *pcbStructInfo = bytesNeeded;
1346 else if (*pcbStructInfo < bytesNeeded)
1348 *pcbStructInfo = bytesNeeded;
1349 SetLastError(ERROR_MORE_DATA);
1350 ret = FALSE;
1352 else
1354 if (dataLen)
1356 const BYTE *ptr;
1357 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1359 *pszObjId = 0;
1360 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1361 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1362 40) * 40);
1363 pszObjId += strlen(pszObjId);
1364 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1365 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1367 int val = 0;
1369 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1370 (*ptr & 0x80))
1372 val <<= 7;
1373 val |= *ptr & 0x7f;
1374 ptr++;
1376 val <<= 7;
1377 val |= *ptr++;
1378 sprintf(pszObjId, ".%d", val);
1379 pszObjId += strlen(pszObjId);
1382 else
1383 *(LPSTR *)pvStructInfo = NULL;
1384 *pcbStructInfo = bytesNeeded;
1387 return ret;
1390 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1391 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1393 BOOL ret;
1395 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1396 pvStructInfo, *pcbStructInfo);
1398 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1399 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1400 pvStructInfo, pcbStructInfo, pcbDecoded);
1401 else
1403 SetLastError(CRYPT_E_ASN1_BADTAG);
1404 ret = FALSE;
1406 return ret;
1409 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1410 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1412 struct AsnDecodeSequenceItem items[] = {
1413 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1414 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1415 offsetof(CERT_EXTENSION, pszObjId), 0 },
1416 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1417 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1418 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1419 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1420 offsetof(CERT_EXTENSION, Value.pbData) },
1422 BOOL ret = TRUE;
1423 PCERT_EXTENSION ext = pvStructInfo;
1425 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1426 *pcbStructInfo);
1428 if (ext)
1429 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1430 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1431 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1432 pcbDecoded, ext ? ext->pszObjId : NULL);
1433 if (ext)
1434 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1435 debugstr_a(ext->pszObjId));
1436 TRACE("returning %d (%08x)\n", ret, GetLastError());
1437 return ret;
1440 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1441 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1442 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1444 BOOL ret = TRUE;
1446 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1447 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
1449 __TRY
1451 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1452 offsetof(CERT_EXTENSIONS, cExtension),
1453 offsetof(CERT_EXTENSIONS, rgExtension),
1454 sizeof(CERT_EXTENSIONS),
1455 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1456 offsetof(CERT_EXTENSION, pszObjId) };
1458 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1459 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1461 __EXCEPT_PAGE_FAULT
1463 SetLastError(STATUS_ACCESS_VIOLATION);
1464 ret = FALSE;
1466 __ENDTRY
1467 return ret;
1470 /* Warning: this assumes the address of value->Value.pbData is already set, in
1471 * order to avoid overwriting memory. (In some cases, it may change it, if it
1472 * doesn't copy anything to memory.) Be sure to set it correctly!
1474 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1475 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1476 DWORD *pcbDecoded)
1478 BOOL ret = TRUE;
1479 DWORD dataLen;
1480 CERT_NAME_VALUE *value = pvStructInfo;
1482 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1484 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1485 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1487 switch (pbEncoded[0])
1489 case ASN_OCTETSTRING:
1490 valueType = CERT_RDN_OCTET_STRING;
1491 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1492 bytesNeeded += dataLen;
1493 break;
1494 case ASN_NUMERICSTRING:
1495 valueType = CERT_RDN_NUMERIC_STRING;
1496 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1497 bytesNeeded += dataLen;
1498 break;
1499 case ASN_PRINTABLESTRING:
1500 valueType = CERT_RDN_PRINTABLE_STRING;
1501 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1502 bytesNeeded += dataLen;
1503 break;
1504 case ASN_IA5STRING:
1505 valueType = CERT_RDN_IA5_STRING;
1506 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1507 bytesNeeded += dataLen;
1508 break;
1509 case ASN_T61STRING:
1510 valueType = CERT_RDN_T61_STRING;
1511 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1512 bytesNeeded += dataLen;
1513 break;
1514 case ASN_VIDEOTEXSTRING:
1515 valueType = CERT_RDN_VIDEOTEX_STRING;
1516 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1517 bytesNeeded += dataLen;
1518 break;
1519 case ASN_GRAPHICSTRING:
1520 valueType = CERT_RDN_GRAPHIC_STRING;
1521 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1522 bytesNeeded += dataLen;
1523 break;
1524 case ASN_VISIBLESTRING:
1525 valueType = CERT_RDN_VISIBLE_STRING;
1526 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1527 bytesNeeded += dataLen;
1528 break;
1529 case ASN_GENERALSTRING:
1530 valueType = CERT_RDN_GENERAL_STRING;
1531 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1532 bytesNeeded += dataLen;
1533 break;
1534 case ASN_UNIVERSALSTRING:
1535 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1536 SetLastError(CRYPT_E_ASN1_BADTAG);
1537 return FALSE;
1538 case ASN_BMPSTRING:
1539 valueType = CERT_RDN_BMP_STRING;
1540 bytesNeeded += dataLen;
1541 break;
1542 case ASN_UTF8STRING:
1543 valueType = CERT_RDN_UTF8_STRING;
1544 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1545 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1546 break;
1547 default:
1548 SetLastError(CRYPT_E_ASN1_BADTAG);
1549 return FALSE;
1552 if (pcbDecoded)
1553 *pcbDecoded = 1 + lenBytes + dataLen;
1554 if (!value)
1555 *pcbStructInfo = bytesNeeded;
1556 else if (*pcbStructInfo < bytesNeeded)
1558 *pcbStructInfo = bytesNeeded;
1559 SetLastError(ERROR_MORE_DATA);
1560 ret = FALSE;
1562 else
1564 *pcbStructInfo = bytesNeeded;
1565 value->dwValueType = valueType;
1566 if (dataLen)
1568 DWORD i;
1570 assert(value->Value.pbData);
1571 switch (pbEncoded[0])
1573 case ASN_OCTETSTRING:
1574 case ASN_NUMERICSTRING:
1575 case ASN_PRINTABLESTRING:
1576 case ASN_IA5STRING:
1577 case ASN_T61STRING:
1578 case ASN_VIDEOTEXSTRING:
1579 case ASN_GRAPHICSTRING:
1580 case ASN_VISIBLESTRING:
1581 case ASN_GENERALSTRING:
1582 value->Value.cbData = dataLen;
1583 if (dataLen)
1585 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1586 memcpy(value->Value.pbData,
1587 pbEncoded + 1 + lenBytes, dataLen);
1588 else
1589 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1590 lenBytes;
1592 break;
1593 case ASN_BMPSTRING:
1595 LPWSTR str = (LPWSTR)value->Value.pbData;
1597 value->Value.cbData = dataLen;
1598 for (i = 0; i < dataLen / 2; i++)
1599 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1600 pbEncoded[1 + lenBytes + 2 * i + 1];
1601 break;
1603 case ASN_UTF8STRING:
1605 LPWSTR str = (LPWSTR)value->Value.pbData;
1607 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1608 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1609 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1610 break;
1614 else
1616 value->Value.cbData = 0;
1617 value->Value.pbData = NULL;
1621 return ret;
1624 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1625 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1626 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1628 BOOL ret = TRUE;
1630 __TRY
1632 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1633 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1634 if (ret && pvStructInfo)
1636 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1637 pcbStructInfo, *pcbStructInfo);
1638 if (ret)
1640 CERT_NAME_VALUE *value;
1642 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1643 pvStructInfo = *(BYTE **)pvStructInfo;
1644 value = pvStructInfo;
1645 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1646 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1647 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1648 pcbStructInfo, NULL);
1652 __EXCEPT_PAGE_FAULT
1654 SetLastError(STATUS_ACCESS_VIOLATION);
1655 ret = FALSE;
1657 __ENDTRY
1658 return ret;
1661 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1662 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1663 DWORD *pcbDecoded)
1665 BOOL ret = TRUE;
1666 DWORD dataLen;
1667 CERT_NAME_VALUE *value = pvStructInfo;
1669 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1671 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1672 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1674 switch (pbEncoded[0])
1676 case ASN_NUMERICSTRING:
1677 valueType = CERT_RDN_NUMERIC_STRING;
1678 if (dataLen)
1679 bytesNeeded += (dataLen + 1) * 2;
1680 break;
1681 case ASN_PRINTABLESTRING:
1682 valueType = CERT_RDN_PRINTABLE_STRING;
1683 if (dataLen)
1684 bytesNeeded += (dataLen + 1) * 2;
1685 break;
1686 case ASN_IA5STRING:
1687 valueType = CERT_RDN_IA5_STRING;
1688 if (dataLen)
1689 bytesNeeded += (dataLen + 1) * 2;
1690 break;
1691 case ASN_T61STRING:
1692 valueType = CERT_RDN_T61_STRING;
1693 if (dataLen)
1694 bytesNeeded += (dataLen + 1) * 2;
1695 break;
1696 case ASN_VIDEOTEXSTRING:
1697 valueType = CERT_RDN_VIDEOTEX_STRING;
1698 if (dataLen)
1699 bytesNeeded += (dataLen + 1) * 2;
1700 break;
1701 case ASN_GRAPHICSTRING:
1702 valueType = CERT_RDN_GRAPHIC_STRING;
1703 if (dataLen)
1704 bytesNeeded += (dataLen + 1) * 2;
1705 break;
1706 case ASN_VISIBLESTRING:
1707 valueType = CERT_RDN_VISIBLE_STRING;
1708 if (dataLen)
1709 bytesNeeded += (dataLen + 1) * 2;
1710 break;
1711 case ASN_GENERALSTRING:
1712 valueType = CERT_RDN_GENERAL_STRING;
1713 if (dataLen)
1714 bytesNeeded += (dataLen + 1) * 2;
1715 break;
1716 case ASN_UNIVERSALSTRING:
1717 valueType = CERT_RDN_UNIVERSAL_STRING;
1718 if (dataLen)
1719 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
1720 break;
1721 case ASN_BMPSTRING:
1722 valueType = CERT_RDN_BMP_STRING;
1723 if (dataLen)
1724 bytesNeeded += dataLen + sizeof(WCHAR);
1725 break;
1726 case ASN_UTF8STRING:
1727 valueType = CERT_RDN_UTF8_STRING;
1728 if (dataLen)
1729 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
1730 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
1731 break;
1732 default:
1733 SetLastError(CRYPT_E_ASN1_BADTAG);
1734 return FALSE;
1737 if (pcbDecoded)
1738 *pcbDecoded = 1 + lenBytes + dataLen;
1739 if (!value)
1740 *pcbStructInfo = bytesNeeded;
1741 else if (*pcbStructInfo < bytesNeeded)
1743 *pcbStructInfo = bytesNeeded;
1744 SetLastError(ERROR_MORE_DATA);
1745 ret = FALSE;
1747 else
1749 *pcbStructInfo = bytesNeeded;
1750 value->dwValueType = valueType;
1751 if (dataLen)
1753 DWORD i;
1754 LPWSTR str = (LPWSTR)value->Value.pbData;
1756 assert(value->Value.pbData);
1757 switch (pbEncoded[0])
1759 case ASN_NUMERICSTRING:
1760 case ASN_PRINTABLESTRING:
1761 case ASN_IA5STRING:
1762 case ASN_T61STRING:
1763 case ASN_VIDEOTEXSTRING:
1764 case ASN_GRAPHICSTRING:
1765 case ASN_VISIBLESTRING:
1766 case ASN_GENERALSTRING:
1767 value->Value.cbData = dataLen * 2;
1768 for (i = 0; i < dataLen; i++)
1769 str[i] = pbEncoded[1 + lenBytes + i];
1770 str[i] = 0;
1771 break;
1772 case ASN_UNIVERSALSTRING:
1773 value->Value.cbData = dataLen / 2;
1774 for (i = 0; i < dataLen / 4; i++)
1775 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1776 | pbEncoded[1 + lenBytes + 2 * i + 3];
1777 str[i] = 0;
1778 break;
1779 case ASN_BMPSTRING:
1780 value->Value.cbData = dataLen;
1781 for (i = 0; i < dataLen / 2; i++)
1782 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1783 pbEncoded[1 + lenBytes + 2 * i + 1];
1784 str[i] = 0;
1785 break;
1786 case ASN_UTF8STRING:
1787 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1788 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1789 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR);
1790 *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0;
1791 value->Value.cbData += sizeof(WCHAR);
1792 break;
1795 else
1797 value->Value.cbData = 0;
1798 value->Value.pbData = NULL;
1802 return ret;
1805 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1806 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1807 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1809 BOOL ret = TRUE;
1811 __TRY
1813 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1814 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1815 if (ret && pvStructInfo)
1817 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1818 pcbStructInfo, *pcbStructInfo);
1819 if (ret)
1821 CERT_NAME_VALUE *value;
1823 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1824 pvStructInfo = *(BYTE **)pvStructInfo;
1825 value = pvStructInfo;
1826 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1827 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1828 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1829 pcbStructInfo, NULL);
1833 __EXCEPT_PAGE_FAULT
1835 SetLastError(STATUS_ACCESS_VIOLATION);
1836 ret = FALSE;
1838 __ENDTRY
1839 return ret;
1842 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1843 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1845 BOOL ret;
1846 struct AsnDecodeSequenceItem items[] = {
1847 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1848 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1849 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1850 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1851 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1852 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1854 CERT_RDN_ATTR *attr = pvStructInfo;
1856 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1857 pvStructInfo, *pcbStructInfo);
1859 if (attr)
1860 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1861 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1862 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1863 attr ? attr->pszObjId : NULL);
1864 if (attr)
1866 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1867 debugstr_a(attr->pszObjId));
1868 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1870 TRACE("returning %d (%08x)\n", ret, GetLastError());
1871 return ret;
1874 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1875 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1877 BOOL ret = TRUE;
1878 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1879 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1880 sizeof(CERT_RDN),
1881 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1882 offsetof(CERT_RDN_ATTR, pszObjId) };
1884 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1885 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1886 return ret;
1889 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1890 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1891 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1893 BOOL ret = TRUE;
1895 __TRY
1897 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1898 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
1899 sizeof(CERT_NAME_INFO),
1900 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1901 offsetof(CERT_RDN, rgRDNAttr) };
1903 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1904 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1906 __EXCEPT_PAGE_FAULT
1908 SetLastError(STATUS_ACCESS_VIOLATION);
1909 ret = FALSE;
1911 __ENDTRY
1912 return ret;
1915 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1916 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1917 DWORD *pcbDecoded)
1919 BOOL ret;
1920 struct AsnDecodeSequenceItem items[] = {
1921 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1922 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1923 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1924 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1925 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1926 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1928 CERT_RDN_ATTR *attr = pvStructInfo;
1930 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1931 pvStructInfo, *pcbStructInfo);
1933 if (attr)
1934 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1935 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1936 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1937 attr ? attr->pszObjId : NULL);
1938 if (attr)
1940 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1941 debugstr_a(attr->pszObjId));
1942 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1944 TRACE("returning %d (%08x)\n", ret, GetLastError());
1945 return ret;
1948 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1949 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1951 BOOL ret = TRUE;
1952 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1953 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1954 sizeof(CERT_RDN),
1955 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1956 offsetof(CERT_RDN_ATTR, pszObjId) };
1958 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1959 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1960 return ret;
1963 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1964 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1965 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1967 BOOL ret = TRUE;
1969 __TRY
1971 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1972 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
1973 sizeof(CERT_NAME_INFO),
1974 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1975 offsetof(CERT_RDN, rgRDNAttr) };
1977 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1978 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1980 __EXCEPT_PAGE_FAULT
1982 SetLastError(STATUS_ACCESS_VIOLATION);
1983 ret = FALSE;
1985 __ENDTRY
1986 return ret;
1989 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1990 DWORD *pcbDecoded)
1992 BOOL ret = TRUE, done = FALSE;
1993 DWORD indefiniteNestingLevels = 0, decoded = 0;
1995 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1997 do {
1998 DWORD dataLen;
2000 if (!cbEncoded)
2001 done = TRUE;
2002 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
2003 &dataLen)))
2005 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2007 if (dataLen == CMSG_INDEFINITE_LENGTH)
2009 indefiniteNestingLevels++;
2010 pbEncoded += 1 + lenBytes;
2011 cbEncoded -= 1 + lenBytes;
2012 decoded += 1 + lenBytes;
2013 TRACE("indefiniteNestingLevels = %d\n",
2014 indefiniteNestingLevels);
2016 else
2018 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
2019 indefiniteNestingLevels)
2021 indefiniteNestingLevels--;
2022 TRACE("indefiniteNestingLevels = %d\n",
2023 indefiniteNestingLevels);
2025 pbEncoded += 1 + lenBytes + dataLen;
2026 cbEncoded -= 1 + lenBytes + dataLen;
2027 decoded += 1 + lenBytes + dataLen;
2028 if (!indefiniteNestingLevels)
2029 done = TRUE;
2032 } while (ret && !done);
2033 /* If we haven't found all 0 TLVs, we haven't found the end */
2034 if (ret && indefiniteNestingLevels)
2036 SetLastError(CRYPT_E_ASN1_EOD);
2037 ret = FALSE;
2039 if (ret)
2040 *pcbDecoded = decoded;
2041 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
2042 return ret;
2045 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
2046 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2047 DWORD *pcbDecoded)
2049 BOOL ret = TRUE;
2050 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
2052 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2053 pvStructInfo, *pcbStructInfo);
2055 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
2057 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2058 bytesNeeded += encodedLen;
2059 if (!pvStructInfo)
2060 *pcbStructInfo = bytesNeeded;
2061 else if (*pcbStructInfo < bytesNeeded)
2063 SetLastError(ERROR_MORE_DATA);
2064 *pcbStructInfo = bytesNeeded;
2065 ret = FALSE;
2067 else
2069 PCRYPT_OBJID_BLOB blob = pvStructInfo;
2071 *pcbStructInfo = bytesNeeded;
2072 blob->cbData = encodedLen;
2073 if (encodedLen)
2075 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2076 blob->pbData = (LPBYTE)pbEncoded;
2077 else
2079 assert(blob->pbData);
2080 memcpy(blob->pbData, pbEncoded, blob->cbData);
2083 else
2084 blob->pbData = NULL;
2086 if (pcbDecoded)
2087 *pcbDecoded = encodedLen;
2089 return ret;
2092 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2093 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2095 BOOL ret;
2096 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2097 offsetof(CTL_USAGE, cUsageIdentifier),
2098 offsetof(CTL_USAGE, rgpszUsageIdentifier),
2099 sizeof(CTL_USAGE),
2100 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2102 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2103 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2104 return ret;
2107 static BOOL CRYPT_AsnDecodeCTLEntryAttributes(const BYTE *pbEncoded,
2108 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2109 DWORD *pcbDecoded)
2111 struct AsnArrayDescriptor arrayDesc = { 0,
2112 offsetof(CTL_ENTRY, cAttribute), offsetof(CTL_ENTRY, rgAttribute),
2113 FINALMEMBERSIZE(CTL_ENTRY, cAttribute),
2114 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2115 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2116 BOOL ret;
2118 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2119 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2120 return ret;
2123 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2124 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2126 struct AsnDecodeSequenceItem items[] = {
2127 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2128 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2129 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2130 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2131 CRYPT_AsnDecodeCTLEntryAttributes,
2132 FINALMEMBERSIZE(CTL_ENTRY, cAttribute), FALSE, TRUE,
2133 offsetof(CTL_ENTRY, rgAttribute), 0 },
2135 BOOL ret = TRUE;
2136 CTL_ENTRY *entry = pvStructInfo;
2138 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2139 *pcbStructInfo);
2141 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2142 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2143 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2144 return ret;
2147 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2148 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2150 BOOL ret;
2151 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2152 offsetof(CTL_INFO, cCTLEntry), offsetof(CTL_INFO, rgCTLEntry),
2153 FINALMEMBERSIZE(CTL_INFO, cExtension),
2154 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2155 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2157 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2158 pvStructInfo, *pcbStructInfo, pcbDecoded);
2160 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2161 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2162 return ret;
2165 static BOOL CRYPT_AsnDecodeCTLExtensionsInternal(const BYTE *pbEncoded,
2166 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2167 DWORD *pcbDecoded)
2169 BOOL ret = TRUE;
2170 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2171 offsetof(CTL_INFO, cExtension), offsetof(CTL_INFO, rgExtension),
2172 FINALMEMBERSIZE(CTL_INFO, cExtension),
2173 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
2174 offsetof(CERT_EXTENSION, pszObjId) };
2176 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2177 pvStructInfo, *pcbStructInfo, pcbDecoded);
2179 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2180 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2181 return ret;
2184 static BOOL CRYPT_AsnDecodeCTLExtensions(const BYTE *pbEncoded,
2185 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2186 DWORD *pcbDecoded)
2188 BOOL ret;
2189 DWORD dataLen;
2191 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2193 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2195 ret = CRYPT_AsnDecodeCTLExtensionsInternal(pbEncoded + 1 + lenBytes,
2196 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2197 if (ret && pcbDecoded)
2198 *pcbDecoded = 1 + lenBytes + dataLen;
2200 return ret;
2203 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2204 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2205 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2207 BOOL ret = FALSE;
2209 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2210 pDecodePara, pvStructInfo, *pcbStructInfo);
2212 __TRY
2214 struct AsnDecodeSequenceItem items[] = {
2215 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2216 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2217 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2218 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2219 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2220 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2221 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
2222 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2223 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2224 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2225 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2226 { 0, offsetof(CTL_INFO, ThisUpdate),
2227 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2228 0 },
2229 { 0, offsetof(CTL_INFO, NextUpdate),
2230 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2231 0 },
2232 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2233 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2234 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2235 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2236 CRYPT_AsnDecodeCTLEntries,
2237 MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension),
2238 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2239 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2240 CRYPT_AsnDecodeCTLExtensions, FINALMEMBERSIZE(CTL_INFO, cExtension),
2241 TRUE, TRUE, offsetof(CTL_INFO, rgExtension), 0 },
2244 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2245 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2246 pcbStructInfo, NULL, NULL);
2248 __EXCEPT_PAGE_FAULT
2250 SetLastError(STATUS_ACCESS_VIOLATION);
2252 __ENDTRY
2253 return ret;
2256 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2257 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2258 DWORD *pcbDecoded)
2260 BOOL ret;
2261 struct AsnDecodeSequenceItem items[] = {
2262 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2263 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2264 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2265 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2266 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2267 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2269 PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
2271 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2272 pvStructInfo, *pcbStructInfo);
2274 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2275 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2276 pcbDecoded, capability ? capability->pszObjId : NULL);
2277 TRACE("returning %d\n", ret);
2278 return ret;
2281 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2282 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2283 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2285 BOOL ret = FALSE;
2287 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2288 pDecodePara, pvStructInfo, *pcbStructInfo);
2290 __TRY
2292 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2293 offsetof(CRYPT_SMIME_CAPABILITIES, cCapability),
2294 offsetof(CRYPT_SMIME_CAPABILITIES, rgCapability),
2295 sizeof(CRYPT_SMIME_CAPABILITIES),
2296 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2297 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2299 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2300 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2302 __EXCEPT_PAGE_FAULT
2304 SetLastError(STATUS_ACCESS_VIOLATION);
2306 __ENDTRY
2307 TRACE("returning %d\n", ret);
2308 return ret;
2311 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
2312 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2313 DWORD *pcbDecoded)
2315 BOOL ret = TRUE;
2316 DWORD dataLen;
2317 LPSTR *pStr = pvStructInfo;
2319 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2321 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2322 DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
2324 if (pbEncoded[0] != ASN_IA5STRING)
2326 SetLastError(CRYPT_E_ASN1_CORRUPT);
2327 ret = FALSE;
2329 else
2331 bytesNeeded += dataLen;
2332 if (pcbDecoded)
2333 *pcbDecoded = 1 + lenBytes + dataLen;
2334 if (!pvStructInfo)
2335 *pcbStructInfo = bytesNeeded;
2336 else if (*pcbStructInfo < bytesNeeded)
2338 *pcbStructInfo = bytesNeeded;
2339 SetLastError(ERROR_MORE_DATA);
2340 ret = FALSE;
2342 else
2344 *pcbStructInfo = bytesNeeded;
2345 if (dataLen)
2347 LPSTR str = *pStr;
2349 assert(str);
2350 memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
2351 str[dataLen] = 0;
2353 else
2354 *pStr = NULL;
2358 return ret;
2361 static BOOL CRYPT_AsnDecodeNoticeNumbers(const BYTE *pbEncoded,
2362 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2363 DWORD *pcbDecoded)
2365 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2366 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2367 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, rgNoticeNumbers),
2368 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2369 CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
2370 BOOL ret;
2372 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2373 pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
2375 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2376 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2377 TRACE("returning %d\n", ret);
2378 return ret;
2381 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
2382 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2383 DWORD *pcbDecoded)
2385 BOOL ret;
2386 struct AsnDecodeSequenceItem items[] = {
2387 { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2388 pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
2389 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
2390 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2391 cNoticeNumbers), CRYPT_AsnDecodeNoticeNumbers,
2392 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2393 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2394 rgNoticeNumbers), 0 },
2396 DWORD bytesNeeded;
2398 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2399 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2401 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2402 pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
2403 NULL);
2404 if (ret)
2406 /* The caller is expecting a pointer to a
2407 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
2408 * CRYPT_AsnDecodeSequence is decoding a
2409 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. Increment the bytes
2410 * needed, and decode again if the requisite space is available.
2412 bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
2413 if (!pvStructInfo)
2414 *pcbStructInfo = bytesNeeded;
2415 else if (*pcbStructInfo < bytesNeeded)
2417 *pcbStructInfo = bytesNeeded;
2418 SetLastError(ERROR_MORE_DATA);
2419 ret = FALSE;
2421 else
2423 PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
2425 *pcbStructInfo = bytesNeeded;
2426 /* The pointer (pvStructInfo) passed in points to the first dynamic
2427 * pointer, so use it as the pointer to the
2428 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
2429 * appropriate offset for the first dynamic pointer within the
2430 * notice reference by pointing to the first memory location past
2431 * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
2433 noticeRef =
2434 *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
2435 noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
2436 sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
2437 ret = CRYPT_AsnDecodeSequence(items,
2438 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2439 NULL, noticeRef, &bytesNeeded, pcbDecoded,
2440 noticeRef->pszOrganization);
2443 TRACE("returning %d\n", ret);
2444 return ret;
2447 static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
2448 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2449 DWORD *pcbDecoded)
2451 BOOL ret = TRUE;
2452 DWORD dataLen;
2454 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2456 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2457 DWORD bytesNeeded = sizeof(LPWSTR);
2459 switch (pbEncoded[0])
2461 case ASN_NUMERICSTRING:
2462 if (dataLen)
2463 bytesNeeded += (dataLen + 1) * 2;
2464 break;
2465 case ASN_PRINTABLESTRING:
2466 if (dataLen)
2467 bytesNeeded += (dataLen + 1) * 2;
2468 break;
2469 case ASN_IA5STRING:
2470 if (dataLen)
2471 bytesNeeded += (dataLen + 1) * 2;
2472 break;
2473 case ASN_T61STRING:
2474 if (dataLen)
2475 bytesNeeded += (dataLen + 1) * 2;
2476 break;
2477 case ASN_VIDEOTEXSTRING:
2478 if (dataLen)
2479 bytesNeeded += (dataLen + 1) * 2;
2480 break;
2481 case ASN_GRAPHICSTRING:
2482 if (dataLen)
2483 bytesNeeded += (dataLen + 1) * 2;
2484 break;
2485 case ASN_VISIBLESTRING:
2486 if (dataLen)
2487 bytesNeeded += (dataLen + 1) * 2;
2488 break;
2489 case ASN_GENERALSTRING:
2490 if (dataLen)
2491 bytesNeeded += (dataLen + 1) * 2;
2492 break;
2493 case ASN_UNIVERSALSTRING:
2494 if (dataLen)
2495 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
2496 break;
2497 case ASN_BMPSTRING:
2498 if (dataLen)
2499 bytesNeeded += dataLen + sizeof(WCHAR);
2500 break;
2501 case ASN_UTF8STRING:
2502 if (dataLen)
2503 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
2504 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
2505 break;
2506 default:
2507 SetLastError(CRYPT_E_ASN1_BADTAG);
2508 return FALSE;
2511 if (pcbDecoded)
2512 *pcbDecoded = 1 + lenBytes + dataLen;
2513 if (!pvStructInfo)
2514 *pcbStructInfo = bytesNeeded;
2515 else if (*pcbStructInfo < bytesNeeded)
2517 *pcbStructInfo = bytesNeeded;
2518 SetLastError(ERROR_MORE_DATA);
2519 ret = FALSE;
2521 else
2523 LPWSTR *pStr = pvStructInfo;
2525 *pcbStructInfo = bytesNeeded;
2526 if (dataLen)
2528 DWORD i;
2529 LPWSTR str = *(LPWSTR *)pStr;
2531 assert(str);
2532 switch (pbEncoded[0])
2534 case ASN_NUMERICSTRING:
2535 case ASN_PRINTABLESTRING:
2536 case ASN_IA5STRING:
2537 case ASN_T61STRING:
2538 case ASN_VIDEOTEXSTRING:
2539 case ASN_GRAPHICSTRING:
2540 case ASN_VISIBLESTRING:
2541 case ASN_GENERALSTRING:
2542 for (i = 0; i < dataLen; i++)
2543 str[i] = pbEncoded[1 + lenBytes + i];
2544 str[i] = 0;
2545 break;
2546 case ASN_UNIVERSALSTRING:
2547 for (i = 0; i < dataLen / 4; i++)
2548 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2549 | pbEncoded[1 + lenBytes + 2 * i + 3];
2550 str[i] = 0;
2551 break;
2552 case ASN_BMPSTRING:
2553 for (i = 0; i < dataLen / 2; i++)
2554 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2555 pbEncoded[1 + lenBytes + 2 * i + 1];
2556 str[i] = 0;
2557 break;
2558 case ASN_UTF8STRING:
2560 int len = MultiByteToWideChar(CP_UTF8, 0,
2561 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2562 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
2563 str[len] = 0;
2564 break;
2568 else
2569 *pStr = NULL;
2572 return ret;
2575 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2576 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2577 DWORD *pcbStructInfo, DWORD *pcbDecoded)
2579 BOOL ret;
2580 struct AsnDecodeSequenceItem items[] = {
2581 { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2582 pNoticeReference), CRYPT_AsnDecodeNoticeReference,
2583 sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
2584 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
2585 { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
2586 CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
2587 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
2589 PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
2591 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2592 pvStructInfo, *pcbStructInfo);
2594 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2595 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2596 pcbDecoded, notice ? notice->pNoticeReference : NULL);
2597 TRACE("returning %d\n", ret);
2598 return ret;
2601 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
2602 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2603 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2604 void *pvStructInfo, DWORD *pcbStructInfo)
2606 BOOL ret = FALSE;
2608 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2609 pDecodePara, pvStructInfo, *pcbStructInfo);
2611 __TRY
2613 DWORD bytesNeeded;
2615 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
2616 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2617 NULL);
2618 if (ret)
2620 if (!pvStructInfo)
2621 *pcbStructInfo = bytesNeeded;
2622 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2623 pvStructInfo, pcbStructInfo, bytesNeeded)))
2625 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
2627 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2628 pvStructInfo = *(BYTE **)pvStructInfo;
2629 notice = pvStructInfo;
2630 notice->pNoticeReference =
2631 (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
2632 ((BYTE *)pvStructInfo +
2633 sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
2634 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2635 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
2636 pvStructInfo, &bytesNeeded, NULL);
2640 __EXCEPT_PAGE_FAULT
2642 SetLastError(STATUS_ACCESS_VIOLATION);
2644 __ENDTRY
2645 TRACE("returning %d\n", ret);
2646 return ret;
2649 static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded,
2650 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2651 DWORD *pcbDecoded)
2653 BOOL ret;
2654 struct AsnArrayDescriptor arrayDesc = { 0,
2655 offsetof(CRYPT_ATTRIBUTE, cValue), offsetof(CRYPT_ATTRIBUTE, rgValue),
2656 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue),
2657 CRYPT_AsnDecodeCopyBytes,
2658 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2660 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2661 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
2663 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2664 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2665 return ret;
2668 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2669 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2670 DWORD *pcbDecoded)
2672 BOOL ret;
2673 struct AsnDecodeSequenceItem items[] = {
2674 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2675 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2676 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2677 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2678 CRYPT_AsnDecodePKCSAttributeValue,
2679 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE,
2680 TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2682 PCRYPT_ATTRIBUTE attr = pvStructInfo;
2684 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2685 pvStructInfo, *pcbStructInfo);
2687 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2688 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2689 pcbDecoded, attr ? attr->pszObjId : NULL);
2690 TRACE("returning %d\n", ret);
2691 return ret;
2694 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2695 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2696 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2698 BOOL ret = FALSE;
2700 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2701 pDecodePara, pvStructInfo, *pcbStructInfo);
2703 __TRY
2705 DWORD bytesNeeded;
2707 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2708 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2709 if (ret)
2711 if (!pvStructInfo)
2712 *pcbStructInfo = bytesNeeded;
2713 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2714 pvStructInfo, pcbStructInfo, bytesNeeded)))
2716 PCRYPT_ATTRIBUTE attr;
2718 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2719 pvStructInfo = *(BYTE **)pvStructInfo;
2720 attr = pvStructInfo;
2721 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2722 sizeof(CRYPT_ATTRIBUTE));
2723 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2724 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2725 NULL);
2729 __EXCEPT_PAGE_FAULT
2731 SetLastError(STATUS_ACCESS_VIOLATION);
2733 __ENDTRY
2734 TRACE("returning %d\n", ret);
2735 return ret;
2738 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2739 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2740 DWORD *pcbDecoded)
2742 struct AsnArrayDescriptor arrayDesc = { 0,
2743 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2744 sizeof(CRYPT_ATTRIBUTES),
2745 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2746 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2747 BOOL ret;
2749 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2750 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2751 return ret;
2754 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2755 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2756 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2758 BOOL ret = FALSE;
2760 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2761 pDecodePara, pvStructInfo, *pcbStructInfo);
2763 __TRY
2765 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
2766 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2767 sizeof(CRYPT_ATTRIBUTES),
2768 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE),
2769 TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2771 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2772 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2774 __EXCEPT_PAGE_FAULT
2776 SetLastError(STATUS_ACCESS_VIOLATION);
2778 __ENDTRY
2779 TRACE("returning %d\n", ret);
2780 return ret;
2783 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2784 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2786 CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
2787 BOOL ret = TRUE;
2788 struct AsnDecodeSequenceItem items[] = {
2789 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2790 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2791 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2792 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2793 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2794 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2797 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2798 pvStructInfo, *pcbStructInfo, pcbDecoded);
2800 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2801 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2802 pcbDecoded, algo ? algo->pszObjId : NULL);
2803 if (ret && pvStructInfo)
2805 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2806 debugstr_a(algo->pszObjId));
2808 return ret;
2811 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2812 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2813 DWORD *pcbDecoded)
2815 BOOL ret = TRUE;
2816 struct AsnDecodeSequenceItem items[] = {
2817 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2818 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2819 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2820 Algorithm.pszObjId) },
2821 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2822 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2823 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2825 PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
2827 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2828 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2829 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2830 return ret;
2833 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2834 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2835 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2837 BOOL ret = TRUE;
2839 __TRY
2841 DWORD bytesNeeded;
2843 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2844 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2846 if (!pvStructInfo)
2847 *pcbStructInfo = bytesNeeded;
2848 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2849 pvStructInfo, pcbStructInfo, bytesNeeded)))
2851 PCERT_PUBLIC_KEY_INFO info;
2853 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2854 pvStructInfo = *(BYTE **)pvStructInfo;
2855 info = pvStructInfo;
2856 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2857 sizeof(CERT_PUBLIC_KEY_INFO);
2858 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2859 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2860 &bytesNeeded, NULL);
2864 __EXCEPT_PAGE_FAULT
2866 SetLastError(STATUS_ACCESS_VIOLATION);
2867 ret = FALSE;
2869 __ENDTRY
2870 return ret;
2873 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2874 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2876 BOOL ret;
2878 if (cbEncoded < 3)
2880 SetLastError(CRYPT_E_ASN1_CORRUPT);
2881 return FALSE;
2883 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2885 SetLastError(CRYPT_E_ASN1_CORRUPT);
2886 return FALSE;
2888 if (pbEncoded[1] > 1)
2890 SetLastError(CRYPT_E_ASN1_CORRUPT);
2891 return FALSE;
2893 if (pcbDecoded)
2894 *pcbDecoded = 3;
2895 if (!pvStructInfo)
2897 *pcbStructInfo = sizeof(BOOL);
2898 ret = TRUE;
2900 else if (*pcbStructInfo < sizeof(BOOL))
2902 *pcbStructInfo = sizeof(BOOL);
2903 SetLastError(ERROR_MORE_DATA);
2904 ret = FALSE;
2906 else
2908 *pcbStructInfo = sizeof(BOOL);
2909 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2910 ret = TRUE;
2912 TRACE("returning %d (%08x)\n", ret, GetLastError());
2913 return ret;
2916 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2917 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2919 PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
2920 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2921 BOOL ret;
2923 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2924 pvStructInfo, *pcbStructInfo);
2926 if (cbEncoded < 2)
2928 SetLastError(CRYPT_E_ASN1_CORRUPT);
2929 return FALSE;
2931 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2932 if (1 + lenBytes > cbEncoded)
2934 SetLastError(CRYPT_E_ASN1_CORRUPT);
2935 return FALSE;
2937 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2939 switch (pbEncoded[0] & ASN_TYPE_MASK)
2941 case 1: /* rfc822Name */
2942 case 2: /* dNSName */
2943 case 6: /* uniformResourceIdentifier */
2944 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2945 break;
2946 case 4: /* directoryName */
2947 case 7: /* iPAddress */
2948 bytesNeeded += dataLen;
2949 break;
2950 case 8: /* registeredID */
2951 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2952 &dataLen, NULL);
2953 if (ret)
2955 /* FIXME: ugly, shouldn't need to know internals of OID decode
2956 * function to use it.
2958 bytesNeeded += dataLen - sizeof(LPSTR);
2960 break;
2961 case 0: /* otherName */
2962 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2963 SetLastError(CRYPT_E_ASN1_BADTAG);
2964 ret = FALSE;
2965 break;
2966 case 3: /* x400Address, unimplemented */
2967 case 5: /* ediPartyName, unimplemented */
2968 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2969 SetLastError(CRYPT_E_ASN1_BADTAG);
2970 ret = FALSE;
2971 break;
2972 default:
2973 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2974 SetLastError(CRYPT_E_ASN1_CORRUPT);
2975 ret = FALSE;
2977 if (ret)
2979 if (pcbDecoded)
2980 *pcbDecoded = 1 + lenBytes + dataLen;
2981 if (!entry)
2982 *pcbStructInfo = bytesNeeded;
2983 else if (*pcbStructInfo < bytesNeeded)
2985 *pcbStructInfo = bytesNeeded;
2986 SetLastError(ERROR_MORE_DATA);
2987 ret = FALSE;
2989 else
2991 *pcbStructInfo = bytesNeeded;
2992 /* MS used values one greater than the asn1 ones.. sigh */
2993 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
2994 switch (pbEncoded[0] & ASN_TYPE_MASK)
2996 case 1: /* rfc822Name */
2997 case 2: /* dNSName */
2998 case 6: /* uniformResourceIdentifier */
3000 DWORD i;
3002 for (i = 0; i < dataLen; i++)
3003 entry->u.pwszURL[i] =
3004 (WCHAR)pbEncoded[1 + lenBytes + i];
3005 entry->u.pwszURL[i] = 0;
3006 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
3007 debugstr_w(entry->u.pwszURL));
3008 break;
3010 case 4: /* directoryName */
3011 /* The data are memory-equivalent with the IPAddress case,
3012 * fall-through
3014 case 7: /* iPAddress */
3015 /* The next data pointer is in the pwszURL spot, that is,
3016 * the first 4 bytes. Need to move it to the next spot.
3018 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
3019 entry->u.IPAddress.cbData = dataLen;
3020 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
3021 dataLen);
3022 break;
3023 case 8: /* registeredID */
3024 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
3025 &entry->u.pszRegisteredID, &dataLen, NULL);
3026 break;
3031 return ret;
3034 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
3035 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3036 DWORD *pcbDecoded)
3038 BOOL ret;
3039 struct AsnArrayDescriptor arrayDesc = { 0,
3040 offsetof(CERT_ALT_NAME_INFO, cAltEntry),
3041 offsetof(CERT_ALT_NAME_INFO, rgAltEntry),
3042 sizeof(CERT_ALT_NAME_INFO),
3043 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3044 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3046 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3047 pvStructInfo, *pcbStructInfo, pcbDecoded);
3049 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3050 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3051 return ret;
3054 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
3055 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
3056 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3057 DWORD *pcbDecoded)
3059 BOOL ret;
3061 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3062 pvStructInfo, *pcbStructInfo, pcbDecoded);
3064 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
3065 * place.
3067 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3068 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
3069 pcbDecoded);
3070 if (ret && pvStructInfo)
3072 CRYPT_DATA_BLOB *blob = pvStructInfo;
3074 if (blob->cbData)
3076 DWORD i;
3077 BYTE temp;
3079 for (i = 0; i < blob->cbData / 2; i++)
3081 temp = blob->pbData[i];
3082 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
3083 blob->pbData[blob->cbData - i - 1] = temp;
3087 TRACE("returning %d (%08x)\n", ret, GetLastError());
3088 return ret;
3091 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
3092 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3093 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3095 BOOL ret;
3097 __TRY
3099 struct AsnDecodeSequenceItem items[] = {
3100 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
3101 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3102 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
3103 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3104 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
3105 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
3106 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
3107 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
3108 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3109 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3110 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
3113 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3114 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3115 pcbStructInfo, NULL, NULL);
3117 __EXCEPT_PAGE_FAULT
3119 SetLastError(STATUS_ACCESS_VIOLATION);
3120 ret = FALSE;
3122 __ENDTRY
3123 return ret;
3126 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
3127 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3128 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3130 BOOL ret;
3132 __TRY
3134 struct AsnDecodeSequenceItem items[] = {
3135 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
3136 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3137 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
3138 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3139 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
3140 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
3141 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3142 AuthorityCertIssuer.rgAltEntry), 0 },
3143 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3144 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3145 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3146 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3147 AuthorityCertSerialNumber.pbData), 0 },
3150 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3151 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3152 pcbStructInfo, NULL, NULL);
3154 __EXCEPT_PAGE_FAULT
3156 SetLastError(STATUS_ACCESS_VIOLATION);
3157 ret = FALSE;
3159 __ENDTRY
3160 return ret;
3163 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
3164 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3165 DWORD *pcbDecoded)
3167 struct AsnDecodeSequenceItem items[] = {
3168 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
3169 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3170 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
3171 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
3172 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
3173 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
3175 CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
3177 return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3178 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3179 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
3182 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
3183 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3184 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3186 BOOL ret;
3188 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3189 pDecodePara, pvStructInfo, *pcbStructInfo);
3191 __TRY
3193 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3194 offsetof(CERT_AUTHORITY_INFO_ACCESS, cAccDescr),
3195 offsetof(CERT_AUTHORITY_INFO_ACCESS, rgAccDescr),
3196 sizeof(CERT_AUTHORITY_INFO_ACCESS),
3197 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
3198 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
3200 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3201 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3203 __EXCEPT_PAGE_FAULT
3205 SetLastError(STATUS_ACCESS_VIOLATION);
3206 ret = FALSE;
3208 __ENDTRY
3209 return ret;
3212 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
3213 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3215 BOOL ret;
3216 DWORD dataLen;
3218 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3219 pvStructInfo, *pcbStructInfo, pcbDecoded);
3221 /* The caller has already checked the tag, no need to check it again.
3222 * Check the outer length is valid:
3224 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
3226 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3227 DWORD innerLen;
3229 pbEncoded += 1 + lenBytes;
3230 cbEncoded -= 1 + lenBytes;
3231 if (dataLen == CMSG_INDEFINITE_LENGTH)
3232 cbEncoded -= 2; /* space for 0 TLV */
3233 /* Check the inner length is valid: */
3234 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
3236 DWORD decodedLen;
3238 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
3239 pvStructInfo, pcbStructInfo, &decodedLen);
3240 if (dataLen == CMSG_INDEFINITE_LENGTH)
3242 if (*(pbEncoded + decodedLen) != 0 ||
3243 *(pbEncoded + decodedLen + 1) != 0)
3245 TRACE("expected 0 TLV, got {%02x,%02x}\n",
3246 *(pbEncoded + decodedLen),
3247 *(pbEncoded + decodedLen + 1));
3248 SetLastError(CRYPT_E_ASN1_CORRUPT);
3249 ret = FALSE;
3251 else
3252 decodedLen += 2;
3254 if (ret && pcbDecoded)
3256 *pcbDecoded = 1 + lenBytes + decodedLen;
3257 TRACE("decoded %d bytes\n", *pcbDecoded);
3261 return ret;
3264 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
3265 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3266 DWORD *pcbDecoded)
3268 CRYPT_CONTENT_INFO *info = pvStructInfo;
3269 struct AsnDecodeSequenceItem items[] = {
3270 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
3271 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3272 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
3273 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
3274 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
3275 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
3276 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
3278 BOOL ret;
3280 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3281 pvStructInfo, *pcbStructInfo, pcbDecoded);
3283 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3284 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3285 pcbDecoded, info ? info->pszObjId : NULL);
3286 return ret;
3289 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
3290 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3291 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3293 BOOL ret = FALSE;
3295 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3296 pDecodePara, pvStructInfo, *pcbStructInfo);
3298 __TRY
3300 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
3301 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3302 if (ret && pvStructInfo)
3304 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3305 pcbStructInfo, *pcbStructInfo);
3306 if (ret)
3308 CRYPT_CONTENT_INFO *info;
3310 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3311 pvStructInfo = *(BYTE **)pvStructInfo;
3312 info = pvStructInfo;
3313 info->pszObjId = (LPSTR)((BYTE *)info +
3314 sizeof(CRYPT_CONTENT_INFO));
3315 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
3316 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3317 pcbStructInfo, NULL);
3321 __EXCEPT_PAGE_FAULT
3323 SetLastError(STATUS_ACCESS_VIOLATION);
3325 __ENDTRY
3326 return ret;
3329 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
3330 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3331 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
3333 BOOL ret;
3334 struct AsnDecodeSequenceItem items[] = {
3335 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
3336 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3337 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
3338 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3339 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
3340 0 },
3341 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
3342 CRYPT_AsnDecodePKCSContentInfoInternal,
3343 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
3344 ContentInfo.pszObjId), 0 },
3345 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
3346 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
3347 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
3350 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3351 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
3352 NULL, NULL);
3353 return ret;
3356 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
3357 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3358 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3360 BOOL ret = TRUE;
3362 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3363 pDecodePara, pvStructInfo, *pcbStructInfo);
3365 __TRY
3367 DWORD bytesNeeded;
3369 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3370 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3372 if (!pvStructInfo)
3373 *pcbStructInfo = bytesNeeded;
3374 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3375 pvStructInfo, pcbStructInfo, bytesNeeded)))
3377 CERT_ALT_NAME_INFO *name;
3379 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3380 pvStructInfo = *(BYTE **)pvStructInfo;
3381 name = pvStructInfo;
3382 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
3383 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
3384 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3385 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3386 &bytesNeeded, NULL);
3390 __EXCEPT_PAGE_FAULT
3392 SetLastError(STATUS_ACCESS_VIOLATION);
3393 ret = FALSE;
3395 __ENDTRY
3396 return ret;
3399 struct PATH_LEN_CONSTRAINT
3401 BOOL fPathLenConstraint;
3402 DWORD dwPathLenConstraint;
3405 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3406 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3407 DWORD *pcbDecoded)
3409 BOOL ret = TRUE;
3410 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3412 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3413 pvStructInfo, *pcbStructInfo, pcbDecoded);
3415 if (!pvStructInfo)
3417 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3418 &size, pcbDecoded);
3419 *pcbStructInfo = bytesNeeded;
3421 else if (*pcbStructInfo < bytesNeeded)
3423 SetLastError(ERROR_MORE_DATA);
3424 *pcbStructInfo = bytesNeeded;
3425 ret = FALSE;
3427 else
3429 struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
3431 *pcbStructInfo = bytesNeeded;
3432 size = sizeof(constraint->dwPathLenConstraint);
3433 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3434 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3435 if (ret)
3436 constraint->fPathLenConstraint = TRUE;
3437 TRACE("got an int, dwPathLenConstraint is %d\n",
3438 constraint->dwPathLenConstraint);
3440 TRACE("returning %d (%08x)\n", ret, GetLastError());
3441 return ret;
3444 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3445 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3446 DWORD *pcbDecoded)
3448 BOOL ret;
3449 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3450 offsetof(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3451 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint),
3452 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3453 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3454 offsetof(CERT_NAME_BLOB, pbData) };
3456 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3457 pvStructInfo, *pcbStructInfo, pcbDecoded);
3459 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3460 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3461 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3462 return ret;
3465 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3466 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3467 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3469 BOOL ret;
3471 __TRY
3473 struct AsnDecodeSequenceItem items[] = {
3474 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3475 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3476 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3477 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3478 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3479 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3480 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3481 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3482 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3483 TRUE, TRUE,
3484 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3487 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3488 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3489 pcbStructInfo, NULL, NULL);
3491 __EXCEPT_PAGE_FAULT
3493 SetLastError(STATUS_ACCESS_VIOLATION);
3494 ret = FALSE;
3496 __ENDTRY
3497 return ret;
3500 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3501 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3502 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3504 BOOL ret;
3506 __TRY
3508 struct AsnDecodeSequenceItem items[] = {
3509 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3510 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3511 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3512 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3513 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3516 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3517 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3518 pcbStructInfo, NULL, NULL);
3520 __EXCEPT_PAGE_FAULT
3522 SetLastError(STATUS_ACCESS_VIOLATION);
3523 ret = FALSE;
3525 __ENDTRY
3526 return ret;
3529 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
3530 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3531 DWORD *pcbDecoded)
3533 struct AsnDecodeSequenceItem items[] = {
3534 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
3535 pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3536 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
3537 0 },
3538 { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
3539 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3540 offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
3542 BOOL ret;
3543 CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
3545 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3546 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3548 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3549 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3550 pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
3551 return ret;
3554 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
3555 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3556 DWORD *pcbDecoded)
3558 BOOL ret;
3559 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3560 offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3561 offsetof(CERT_POLICY_INFO, rgPolicyQualifier),
3562 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier),
3563 CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
3564 offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
3566 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3567 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3569 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3570 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3571 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3572 return ret;
3575 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
3576 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3578 struct AsnDecodeSequenceItem items[] = {
3579 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
3580 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3581 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
3582 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3583 CRYPT_AsnDecodePolicyQualifiers,
3584 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier), TRUE,
3585 TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
3587 CERT_POLICY_INFO *info = pvStructInfo;
3588 BOOL ret;
3590 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3591 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3593 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3594 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3595 pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
3596 return ret;
3599 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
3600 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3601 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3603 BOOL ret = FALSE;
3605 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3606 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3608 __TRY
3610 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3611 offsetof(CERT_POLICIES_INFO, cPolicyInfo),
3612 offsetof(CERT_POLICIES_INFO, rgPolicyInfo),
3613 sizeof(CERT_POLICIES_INFO),
3614 CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
3615 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
3617 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3618 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3620 __EXCEPT_PAGE_FAULT
3622 SetLastError(STATUS_ACCESS_VIOLATION);
3624 __ENDTRY
3625 return ret;
3628 #define RSA1_MAGIC 0x31415352
3630 struct DECODED_RSA_PUB_KEY
3632 DWORD pubexp;
3633 CRYPT_INTEGER_BLOB modulus;
3636 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3637 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3638 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3640 BOOL ret;
3642 __TRY
3644 struct AsnDecodeSequenceItem items[] = {
3645 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3646 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3647 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3648 0 },
3649 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3650 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3652 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3653 DWORD size = 0;
3655 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3656 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3657 &size, NULL, NULL);
3658 if (ret)
3660 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3661 decodedKey->modulus.cbData;
3663 if (!pvStructInfo)
3665 *pcbStructInfo = bytesNeeded;
3666 ret = TRUE;
3668 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3669 pvStructInfo, pcbStructInfo, bytesNeeded)))
3671 BLOBHEADER *hdr;
3672 RSAPUBKEY *rsaPubKey;
3674 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3675 pvStructInfo = *(BYTE **)pvStructInfo;
3676 hdr = pvStructInfo;
3677 hdr->bType = PUBLICKEYBLOB;
3678 hdr->bVersion = CUR_BLOB_VERSION;
3679 hdr->reserved = 0;
3680 hdr->aiKeyAlg = CALG_RSA_KEYX;
3681 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3682 sizeof(BLOBHEADER));
3683 rsaPubKey->magic = RSA1_MAGIC;
3684 rsaPubKey->pubexp = decodedKey->pubexp;
3685 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3686 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3687 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3688 decodedKey->modulus.cbData);
3690 LocalFree(decodedKey);
3693 __EXCEPT_PAGE_FAULT
3695 SetLastError(STATUS_ACCESS_VIOLATION);
3696 ret = FALSE;
3698 __ENDTRY
3699 return ret;
3702 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
3703 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3704 DWORD *pcbDecoded)
3706 BOOL ret;
3707 DWORD bytesNeeded, dataLen;
3709 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3710 pvStructInfo, *pcbStructInfo, pcbDecoded);
3712 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3714 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3716 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3717 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
3718 else
3719 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
3720 if (pcbDecoded)
3721 *pcbDecoded = 1 + lenBytes + dataLen;
3722 if (!pvStructInfo)
3723 *pcbStructInfo = bytesNeeded;
3724 else if (*pcbStructInfo < bytesNeeded)
3726 SetLastError(ERROR_MORE_DATA);
3727 *pcbStructInfo = bytesNeeded;
3728 ret = FALSE;
3730 else
3732 CRYPT_DATA_BLOB *blob;
3734 *pcbStructInfo = bytesNeeded;
3735 blob = pvStructInfo;
3736 blob->cbData = dataLen;
3737 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3738 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
3739 else
3741 assert(blob->pbData);
3742 if (blob->cbData)
3743 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
3744 blob->cbData);
3748 return ret;
3751 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
3752 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3753 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3755 BOOL ret;
3757 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3758 pDecodePara, pvStructInfo, *pcbStructInfo);
3760 __TRY
3762 DWORD bytesNeeded;
3764 if (!cbEncoded)
3766 SetLastError(CRYPT_E_ASN1_CORRUPT);
3767 ret = FALSE;
3769 else if (pbEncoded[0] != ASN_OCTETSTRING)
3771 SetLastError(CRYPT_E_ASN1_BADTAG);
3772 ret = FALSE;
3774 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3775 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3777 if (!pvStructInfo)
3778 *pcbStructInfo = bytesNeeded;
3779 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3780 pvStructInfo, pcbStructInfo, bytesNeeded)))
3782 CRYPT_DATA_BLOB *blob;
3784 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3785 pvStructInfo = *(BYTE **)pvStructInfo;
3786 blob = pvStructInfo;
3787 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
3788 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3789 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3790 &bytesNeeded, NULL);
3794 __EXCEPT_PAGE_FAULT
3796 SetLastError(STATUS_ACCESS_VIOLATION);
3797 ret = FALSE;
3799 __ENDTRY
3800 return ret;
3803 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3804 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3806 BOOL ret;
3807 DWORD bytesNeeded, dataLen;
3808 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3810 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3811 pvStructInfo, *pcbStructInfo, pcbDecoded);
3813 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3815 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3816 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3817 else
3818 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3819 if (pcbDecoded)
3820 *pcbDecoded = 1 + lenBytes + dataLen;
3821 if (!pvStructInfo)
3822 *pcbStructInfo = bytesNeeded;
3823 else if (*pcbStructInfo < bytesNeeded)
3825 *pcbStructInfo = bytesNeeded;
3826 SetLastError(ERROR_MORE_DATA);
3827 ret = FALSE;
3829 else
3831 CRYPT_BIT_BLOB *blob;
3833 *pcbStructInfo = bytesNeeded;
3834 blob = pvStructInfo;
3835 blob->cbData = dataLen - 1;
3836 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3837 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3839 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3841 else
3843 assert(blob->pbData);
3844 if (blob->cbData)
3846 BYTE mask = 0xff << blob->cUnusedBits;
3848 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3849 blob->cbData);
3850 blob->pbData[blob->cbData - 1] &= mask;
3855 return ret;
3858 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3859 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3860 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3862 BOOL ret;
3864 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3865 pDecodePara, pvStructInfo, pcbStructInfo);
3867 __TRY
3869 DWORD bytesNeeded;
3871 if (!cbEncoded)
3873 SetLastError(CRYPT_E_ASN1_CORRUPT);
3874 ret = FALSE;
3876 else if (pbEncoded[0] != ASN_BITSTRING)
3878 SetLastError(CRYPT_E_ASN1_BADTAG);
3879 ret = FALSE;
3881 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3882 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3884 if (!pvStructInfo)
3885 *pcbStructInfo = bytesNeeded;
3886 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3887 pvStructInfo, pcbStructInfo, bytesNeeded)))
3889 CRYPT_BIT_BLOB *blob;
3891 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3892 pvStructInfo = *(BYTE **)pvStructInfo;
3893 blob = pvStructInfo;
3894 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3895 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3896 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3897 &bytesNeeded, NULL);
3901 __EXCEPT_PAGE_FAULT
3903 SetLastError(STATUS_ACCESS_VIOLATION);
3904 ret = FALSE;
3906 __ENDTRY
3907 TRACE("returning %d (%08x)\n", ret, GetLastError());
3908 return ret;
3911 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
3912 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3913 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3915 BOOL ret;
3916 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3917 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3918 DWORD size = sizeof(buf);
3920 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3921 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, buf,
3922 &size, pcbDecoded);
3923 if (ret)
3925 if (!pvStructInfo)
3926 *pcbStructInfo = sizeof(int);
3927 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3929 int val, i;
3931 if (blob->pbData[blob->cbData - 1] & 0x80)
3933 /* initialize to a negative value to sign-extend */
3934 val = -1;
3936 else
3937 val = 0;
3938 for (i = 0; i < blob->cbData; i++)
3940 val <<= 8;
3941 val |= blob->pbData[blob->cbData - i - 1];
3943 memcpy(pvStructInfo, &val, sizeof(int));
3946 else if (GetLastError() == ERROR_MORE_DATA)
3947 SetLastError(CRYPT_E_ASN1_LARGE);
3948 return ret;
3951 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3952 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3953 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3955 BOOL ret;
3957 __TRY
3959 DWORD bytesNeeded;
3961 if (!cbEncoded)
3963 SetLastError(CRYPT_E_ASN1_EOD);
3964 ret = FALSE;
3966 else if (pbEncoded[0] != ASN_INTEGER)
3968 SetLastError(CRYPT_E_ASN1_BADTAG);
3969 ret = FALSE;
3971 else
3972 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3973 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3974 if (ret)
3976 if (!pvStructInfo)
3977 *pcbStructInfo = bytesNeeded;
3978 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3979 pvStructInfo, pcbStructInfo, bytesNeeded)))
3981 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3982 pvStructInfo = *(BYTE **)pvStructInfo;
3983 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3984 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3985 &bytesNeeded, NULL);
3989 __EXCEPT_PAGE_FAULT
3991 SetLastError(STATUS_ACCESS_VIOLATION);
3992 ret = FALSE;
3994 __ENDTRY
3995 return ret;
3998 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3999 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4000 DWORD *pcbDecoded)
4002 BOOL ret;
4003 DWORD bytesNeeded, dataLen;
4005 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4007 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4009 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4010 if (pcbDecoded)
4011 *pcbDecoded = 1 + lenBytes + dataLen;
4012 if (!pvStructInfo)
4013 *pcbStructInfo = bytesNeeded;
4014 else if (*pcbStructInfo < bytesNeeded)
4016 *pcbStructInfo = bytesNeeded;
4017 SetLastError(ERROR_MORE_DATA);
4018 ret = FALSE;
4020 else
4022 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4024 *pcbStructInfo = bytesNeeded;
4025 blob->cbData = dataLen;
4026 assert(blob->pbData);
4027 if (blob->cbData)
4029 DWORD i;
4031 for (i = 0; i < blob->cbData; i++)
4033 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4034 dataLen - i - 1);
4039 return ret;
4042 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4043 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4044 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4046 BOOL ret;
4048 __TRY
4050 DWORD bytesNeeded;
4052 if (pbEncoded[0] != ASN_INTEGER)
4054 SetLastError(CRYPT_E_ASN1_BADTAG);
4055 ret = FALSE;
4057 else
4058 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4059 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4060 if (ret)
4062 if (!pvStructInfo)
4063 *pcbStructInfo = bytesNeeded;
4064 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4065 pvStructInfo, pcbStructInfo, bytesNeeded)))
4067 CRYPT_INTEGER_BLOB *blob;
4069 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4070 pvStructInfo = *(BYTE **)pvStructInfo;
4071 blob = pvStructInfo;
4072 blob->pbData = (BYTE *)pvStructInfo +
4073 sizeof(CRYPT_INTEGER_BLOB);
4074 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4075 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4076 &bytesNeeded, NULL);
4080 __EXCEPT_PAGE_FAULT
4082 SetLastError(STATUS_ACCESS_VIOLATION);
4083 ret = FALSE;
4085 __ENDTRY
4086 return ret;
4089 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
4090 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4091 DWORD *pcbDecoded)
4093 BOOL ret;
4095 if (pbEncoded[0] == ASN_INTEGER)
4097 DWORD bytesNeeded, dataLen;
4099 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4101 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4103 if (pcbDecoded)
4104 *pcbDecoded = 1 + lenBytes + dataLen;
4105 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4106 if (!pvStructInfo)
4107 *pcbStructInfo = bytesNeeded;
4108 else if (*pcbStructInfo < bytesNeeded)
4110 *pcbStructInfo = bytesNeeded;
4111 SetLastError(ERROR_MORE_DATA);
4112 ret = FALSE;
4114 else
4116 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4118 *pcbStructInfo = bytesNeeded;
4119 blob->cbData = dataLen;
4120 assert(blob->pbData);
4121 /* remove leading zero byte if it exists */
4122 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4124 blob->cbData--;
4125 blob->pbData++;
4127 if (blob->cbData)
4129 DWORD i;
4131 for (i = 0; i < blob->cbData; i++)
4133 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4134 dataLen - i - 1);
4140 else
4142 SetLastError(CRYPT_E_ASN1_BADTAG);
4143 ret = FALSE;
4145 return ret;
4148 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4149 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4150 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4152 BOOL ret;
4154 __TRY
4156 DWORD bytesNeeded;
4158 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4159 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4161 if (!pvStructInfo)
4162 *pcbStructInfo = bytesNeeded;
4163 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4164 pvStructInfo, pcbStructInfo, bytesNeeded)))
4166 CRYPT_INTEGER_BLOB *blob;
4168 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4169 pvStructInfo = *(BYTE **)pvStructInfo;
4170 blob = pvStructInfo;
4171 blob->pbData = (BYTE *)pvStructInfo +
4172 sizeof(CRYPT_INTEGER_BLOB);
4173 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4174 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4175 &bytesNeeded, NULL);
4179 __EXCEPT_PAGE_FAULT
4181 SetLastError(STATUS_ACCESS_VIOLATION);
4182 ret = FALSE;
4184 __ENDTRY
4185 return ret;
4188 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4189 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4190 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4192 BOOL ret;
4194 if (!pvStructInfo)
4196 *pcbStructInfo = sizeof(int);
4197 return TRUE;
4199 __TRY
4201 if (pbEncoded[0] == ASN_ENUMERATED)
4203 unsigned int val = 0, i;
4205 if (cbEncoded <= 1)
4207 SetLastError(CRYPT_E_ASN1_EOD);
4208 ret = FALSE;
4210 else if (pbEncoded[1] == 0)
4212 SetLastError(CRYPT_E_ASN1_CORRUPT);
4213 ret = FALSE;
4215 else
4217 /* A little strange looking, but we have to accept a sign byte:
4218 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4219 * assuming a small length is okay here, it has to be in short
4220 * form.
4222 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4224 SetLastError(CRYPT_E_ASN1_LARGE);
4225 return FALSE;
4227 for (i = 0; i < pbEncoded[1]; i++)
4229 val <<= 8;
4230 val |= pbEncoded[2 + i];
4232 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4233 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4235 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4236 pvStructInfo = *(BYTE **)pvStructInfo;
4237 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4241 else
4243 SetLastError(CRYPT_E_ASN1_BADTAG);
4244 ret = FALSE;
4247 __EXCEPT_PAGE_FAULT
4249 SetLastError(STATUS_ACCESS_VIOLATION);
4250 ret = FALSE;
4252 __ENDTRY
4253 return ret;
4256 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4257 * if it fails.
4259 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4260 do { \
4261 BYTE i; \
4263 (word) = 0; \
4264 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4266 if (!isdigit(*(pbEncoded))) \
4268 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4269 ret = FALSE; \
4271 else \
4273 (word) *= 10; \
4274 (word) += *(pbEncoded)++ - '0'; \
4277 } while (0)
4279 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4280 SYSTEMTIME *sysTime)
4282 BOOL ret = TRUE;
4284 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4286 WORD hours, minutes = 0;
4287 BYTE sign = *pbEncoded++;
4289 len--;
4290 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4291 if (ret && hours >= 24)
4293 SetLastError(CRYPT_E_ASN1_CORRUPT);
4294 ret = FALSE;
4296 else if (len >= 2)
4298 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4299 if (ret && minutes >= 60)
4301 SetLastError(CRYPT_E_ASN1_CORRUPT);
4302 ret = FALSE;
4305 if (ret)
4307 if (sign == '+')
4309 sysTime->wHour += hours;
4310 sysTime->wMinute += minutes;
4312 else
4314 if (hours > sysTime->wHour)
4316 sysTime->wDay--;
4317 sysTime->wHour = 24 - (hours - sysTime->wHour);
4319 else
4320 sysTime->wHour -= hours;
4321 if (minutes > sysTime->wMinute)
4323 sysTime->wHour--;
4324 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4326 else
4327 sysTime->wMinute -= minutes;
4331 return ret;
4334 #define MIN_ENCODED_TIME_LENGTH 10
4336 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4337 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4338 DWORD *pcbDecoded)
4340 BOOL ret = FALSE;
4342 if (pbEncoded[0] == ASN_UTCTIME)
4344 if (cbEncoded <= 1)
4345 SetLastError(CRYPT_E_ASN1_EOD);
4346 else if (pbEncoded[1] > 0x7f)
4348 /* long-form date strings really can't be valid */
4349 SetLastError(CRYPT_E_ASN1_CORRUPT);
4351 else
4353 SYSTEMTIME sysTime = { 0 };
4354 BYTE len = pbEncoded[1];
4356 if (len < MIN_ENCODED_TIME_LENGTH)
4357 SetLastError(CRYPT_E_ASN1_CORRUPT);
4358 else
4360 ret = TRUE;
4361 if (pcbDecoded)
4362 *pcbDecoded = 2 + len;
4363 pbEncoded += 2;
4364 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4365 if (sysTime.wYear >= 50)
4366 sysTime.wYear += 1900;
4367 else
4368 sysTime.wYear += 2000;
4369 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4370 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4371 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4372 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4373 if (ret && len > 0)
4375 if (len >= 2 && isdigit(*pbEncoded) &&
4376 isdigit(*(pbEncoded + 1)))
4377 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4378 sysTime.wSecond);
4379 else if (isdigit(*pbEncoded))
4380 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4381 sysTime.wSecond);
4382 if (ret)
4383 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4384 &sysTime);
4386 if (ret)
4388 if (!pvStructInfo)
4389 *pcbStructInfo = sizeof(FILETIME);
4390 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4391 sizeof(FILETIME))))
4392 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4397 else
4398 SetLastError(CRYPT_E_ASN1_BADTAG);
4399 return ret;
4402 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4403 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4404 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4406 BOOL ret = FALSE;
4408 __TRY
4410 DWORD bytesNeeded;
4412 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4413 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4414 if (ret)
4416 if (!pvStructInfo)
4417 *pcbStructInfo = bytesNeeded;
4418 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4419 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4421 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4422 pvStructInfo = *(BYTE **)pvStructInfo;
4423 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4424 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4425 &bytesNeeded, NULL);
4429 __EXCEPT_PAGE_FAULT
4431 SetLastError(STATUS_ACCESS_VIOLATION);
4433 __ENDTRY
4434 return ret;
4437 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
4438 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4439 DWORD *pcbDecoded)
4441 BOOL ret = FALSE;
4443 if (pbEncoded[0] == ASN_GENERALTIME)
4445 if (cbEncoded <= 1)
4446 SetLastError(CRYPT_E_ASN1_EOD);
4447 else if (pbEncoded[1] > 0x7f)
4449 /* long-form date strings really can't be valid */
4450 SetLastError(CRYPT_E_ASN1_CORRUPT);
4452 else
4454 BYTE len = pbEncoded[1];
4456 if (len < MIN_ENCODED_TIME_LENGTH)
4457 SetLastError(CRYPT_E_ASN1_CORRUPT);
4458 else
4460 SYSTEMTIME sysTime = { 0 };
4462 ret = TRUE;
4463 if (pcbDecoded)
4464 *pcbDecoded = 2 + len;
4465 pbEncoded += 2;
4466 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
4467 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4468 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4469 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4470 if (ret && len > 0)
4472 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4473 sysTime.wMinute);
4474 if (ret && len > 0)
4475 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4476 sysTime.wSecond);
4477 if (ret && len > 0 && (*pbEncoded == '.' ||
4478 *pbEncoded == ','))
4480 BYTE digits;
4482 pbEncoded++;
4483 len--;
4484 /* workaround macro weirdness */
4485 digits = min(len, 3);
4486 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
4487 sysTime.wMilliseconds);
4489 if (ret)
4490 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4491 &sysTime);
4493 if (ret)
4495 if (!pvStructInfo)
4496 *pcbStructInfo = sizeof(FILETIME);
4497 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4498 sizeof(FILETIME))))
4499 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4504 else
4505 SetLastError(CRYPT_E_ASN1_BADTAG);
4506 return ret;
4509 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4510 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4511 DWORD *pcbDecoded)
4513 BOOL ret;
4514 InternalDecodeFunc decode = NULL;
4516 if (pbEncoded[0] == ASN_UTCTIME)
4517 decode = CRYPT_AsnDecodeUtcTimeInternal;
4518 else if (pbEncoded[0] == ASN_GENERALTIME)
4519 decode = CRYPT_AsnDecodeGeneralizedTime;
4520 if (decode)
4521 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
4522 pcbStructInfo, pcbDecoded);
4523 else
4525 SetLastError(CRYPT_E_ASN1_BADTAG);
4526 ret = FALSE;
4528 return ret;
4531 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
4532 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4533 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4535 BOOL ret;
4537 __TRY
4539 DWORD bytesNeeded;
4541 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4542 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4543 if (ret)
4545 if (!pvStructInfo)
4546 *pcbStructInfo = bytesNeeded;
4547 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4548 pvStructInfo, pcbStructInfo, bytesNeeded)))
4550 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4551 pvStructInfo = *(BYTE **)pvStructInfo;
4552 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4553 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4554 &bytesNeeded, NULL);
4558 __EXCEPT_PAGE_FAULT
4560 SetLastError(STATUS_ACCESS_VIOLATION);
4561 ret = FALSE;
4563 __ENDTRY
4564 return ret;
4567 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
4568 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4569 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4571 BOOL ret = TRUE;
4573 __TRY
4575 if (pbEncoded[0] == ASN_SEQUENCEOF)
4577 DWORD bytesNeeded, dataLen, remainingLen, cValue;
4579 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4581 BYTE lenBytes;
4582 const BYTE *ptr;
4584 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4585 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
4586 cValue = 0;
4587 ptr = pbEncoded + 1 + lenBytes;
4588 remainingLen = dataLen;
4589 while (ret && remainingLen)
4591 DWORD nextLen;
4593 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4594 if (ret)
4596 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4598 remainingLen -= 1 + nextLenBytes + nextLen;
4599 ptr += 1 + nextLenBytes + nextLen;
4600 bytesNeeded += sizeof(CRYPT_DER_BLOB);
4601 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
4602 bytesNeeded += 1 + nextLenBytes + nextLen;
4603 cValue++;
4606 if (ret)
4608 CRYPT_SEQUENCE_OF_ANY *seq;
4609 BYTE *nextPtr;
4610 DWORD i;
4612 if (!pvStructInfo)
4613 *pcbStructInfo = bytesNeeded;
4614 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4615 pvStructInfo, pcbStructInfo, bytesNeeded)))
4617 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4618 pvStructInfo = *(BYTE **)pvStructInfo;
4619 seq = pvStructInfo;
4620 seq->cValue = cValue;
4621 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
4622 sizeof(*seq));
4623 nextPtr = (BYTE *)seq->rgValue +
4624 cValue * sizeof(CRYPT_DER_BLOB);
4625 ptr = pbEncoded + 1 + lenBytes;
4626 remainingLen = dataLen;
4627 i = 0;
4628 while (ret && remainingLen)
4630 DWORD nextLen;
4632 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4633 if (ret)
4635 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4637 seq->rgValue[i].cbData = 1 + nextLenBytes +
4638 nextLen;
4639 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4640 seq->rgValue[i].pbData = (BYTE *)ptr;
4641 else
4643 seq->rgValue[i].pbData = nextPtr;
4644 memcpy(nextPtr, ptr, 1 + nextLenBytes +
4645 nextLen);
4646 nextPtr += 1 + nextLenBytes + nextLen;
4648 remainingLen -= 1 + nextLenBytes + nextLen;
4649 ptr += 1 + nextLenBytes + nextLen;
4650 i++;
4657 else
4659 SetLastError(CRYPT_E_ASN1_BADTAG);
4660 ret = FALSE;
4663 __EXCEPT_PAGE_FAULT
4665 SetLastError(STATUS_ACCESS_VIOLATION);
4666 ret = FALSE;
4668 __ENDTRY
4669 return ret;
4672 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4673 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4674 DWORD *pcbDecoded)
4676 BOOL ret;
4678 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
4680 DWORD bytesNeeded, dataLen;
4682 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4684 struct AsnArrayDescriptor arrayDesc = {
4685 ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4686 offsetof(CRL_DIST_POINT_NAME, u.FullName.cAltEntry),
4687 offsetof(CRL_DIST_POINT_NAME, u.FullName.rgAltEntry),
4688 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u),
4689 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
4690 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
4691 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4692 DWORD nameLen;
4694 if (dataLen)
4696 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4697 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4698 dwFlags, NULL, NULL, &nameLen, NULL);
4699 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
4700 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u);
4702 else
4703 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
4704 if (pcbDecoded)
4705 *pcbDecoded = 1 + lenBytes + dataLen;
4706 if (!pvStructInfo)
4707 *pcbStructInfo = bytesNeeded;
4708 else if (*pcbStructInfo < bytesNeeded)
4710 *pcbStructInfo = bytesNeeded;
4711 SetLastError(ERROR_MORE_DATA);
4712 ret = FALSE;
4714 else
4716 CRL_DIST_POINT_NAME *name = pvStructInfo;
4718 *pcbStructInfo = bytesNeeded;
4719 if (dataLen)
4721 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
4722 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4723 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4724 dwFlags, NULL, &name->u.FullName.cAltEntry, &nameLen,
4725 NULL);
4727 else
4728 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
4732 else
4734 SetLastError(CRYPT_E_ASN1_BADTAG);
4735 ret = FALSE;
4737 return ret;
4740 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
4741 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4743 struct AsnDecodeSequenceItem items[] = {
4744 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
4745 DistPointName), CRYPT_AsnDecodeDistPointName,
4746 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
4747 DistPointName.u.FullName.rgAltEntry), 0 },
4748 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
4749 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
4750 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
4751 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
4752 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
4753 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
4755 CRL_DIST_POINT *point = pvStructInfo;
4756 BOOL ret;
4758 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4759 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4760 pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
4761 return ret;
4764 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
4765 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4766 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4768 BOOL ret;
4770 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4771 pDecodePara, pvStructInfo, *pcbStructInfo);
4773 __TRY
4775 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4776 offsetof(CRL_DIST_POINTS_INFO, cDistPoint),
4777 offsetof(CRL_DIST_POINTS_INFO, rgDistPoint),
4778 sizeof(CRL_DIST_POINTS_INFO),
4779 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
4780 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
4782 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
4783 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
4785 __EXCEPT_PAGE_FAULT
4787 SetLastError(STATUS_ACCESS_VIOLATION);
4788 ret = FALSE;
4790 __ENDTRY
4791 return ret;
4794 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
4795 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4796 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4798 BOOL ret;
4800 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4801 pDecodePara, pvStructInfo, *pcbStructInfo);
4803 __TRY
4805 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4806 offsetof(CERT_ENHKEY_USAGE, cUsageIdentifier),
4807 offsetof(CERT_ENHKEY_USAGE, rgpszUsageIdentifier),
4808 sizeof(CERT_ENHKEY_USAGE),
4809 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4811 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
4812 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
4814 __EXCEPT_PAGE_FAULT
4816 SetLastError(STATUS_ACCESS_VIOLATION);
4817 ret = FALSE;
4819 __ENDTRY
4820 return ret;
4823 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4824 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4825 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4827 BOOL ret;
4829 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4830 pDecodePara, pvStructInfo, *pcbStructInfo);
4832 __TRY
4834 struct AsnDecodeSequenceItem items[] = {
4835 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4836 DistPointName), CRYPT_AsnDecodeDistPointName,
4837 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4838 offsetof(CRL_ISSUING_DIST_POINT,
4839 DistPointName.u.FullName.rgAltEntry), 0 },
4840 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4841 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4842 FALSE, 0 },
4843 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4844 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4845 FALSE, 0 },
4846 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4847 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4848 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4849 OnlySomeReasonFlags.pbData), 0 },
4850 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4851 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4854 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4855 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4856 pcbStructInfo, NULL, NULL);
4858 __EXCEPT_PAGE_FAULT
4860 SetLastError(STATUS_ACCESS_VIOLATION);
4861 ret = FALSE;
4863 __ENDTRY
4864 return ret;
4867 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
4868 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4869 DWORD *pcbDecoded)
4871 BOOL ret = FALSE;
4873 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4874 pvStructInfo, *pcbStructInfo, pcbDecoded);
4876 if (!cbEncoded)
4878 SetLastError(CRYPT_E_ASN1_EOD);
4879 return FALSE;
4881 if (pbEncoded[0] != (ASN_CONTEXT | 1))
4883 SetLastError(CRYPT_E_ASN1_BADTAG);
4884 return FALSE;
4886 /* The BOOL is implicit: if the integer is present, then it's TRUE */
4887 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
4888 pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo,
4889 pcbDecoded);
4890 if (ret && pvStructInfo)
4891 *(BOOL *)pvStructInfo = TRUE;
4892 TRACE("returning %d\n", ret);
4893 return ret;
4896 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
4897 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4898 DWORD *pcbDecoded)
4900 BOOL ret;
4901 struct AsnDecodeSequenceItem items[] = {
4902 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
4903 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
4904 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
4905 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
4906 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
4907 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
4908 CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0,
4909 0 },
4911 CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
4913 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4914 pvStructInfo, *pcbStructInfo, pcbDecoded);
4916 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4917 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4918 pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
4919 if (pcbDecoded)
4921 TRACE("%d\n", *pcbDecoded);
4922 if (*pcbDecoded < cbEncoded)
4923 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
4924 *(pbEncoded + *pcbDecoded + 1));
4926 TRACE("returning %d\n", ret);
4927 return ret;
4930 static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
4931 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4932 DWORD *pcbDecoded)
4934 BOOL ret = TRUE;
4935 struct AsnArrayDescriptor arrayDesc = { 0,
4936 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
4937 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree),
4938 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
4939 cExcludedSubtree),
4940 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4941 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4943 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4944 pvStructInfo, *pcbStructInfo, pcbDecoded);
4946 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
4947 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
4948 return ret;
4951 static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
4952 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4953 DWORD *pcbDecoded)
4955 BOOL ret = TRUE;
4956 struct AsnArrayDescriptor arrayDesc = { 0,
4957 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4958 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree),
4959 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4960 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4961 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4963 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4964 pvStructInfo, *pcbStructInfo, pcbDecoded);
4966 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
4967 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
4968 return ret;
4971 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
4972 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4973 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4975 BOOL ret = FALSE;
4977 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4978 pDecodePara, pvStructInfo, *pcbStructInfo);
4980 __TRY
4982 struct AsnDecodeSequenceItem items[] = {
4983 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4984 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
4985 CRYPT_AsnDecodePermittedSubtree,
4986 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
4987 cExcludedSubtree), TRUE, TRUE,
4988 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
4989 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
4990 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4991 CRYPT_AsnDecodeExcludedSubtree,
4992 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4993 TRUE, TRUE,
4994 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
4997 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4998 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4999 pcbStructInfo, NULL, NULL);
5001 __EXCEPT_PAGE_FAULT
5003 SetLastError(STATUS_ACCESS_VIOLATION);
5005 __ENDTRY
5006 return ret;
5009 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
5010 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5011 DWORD *pcbDecoded)
5013 BOOL ret;
5014 struct AsnDecodeSequenceItem items[] = {
5015 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
5016 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
5017 Issuer.pbData) },
5018 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
5019 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
5020 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
5022 CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
5024 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5025 pvStructInfo, *pcbStructInfo, pcbDecoded);
5027 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5028 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5029 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
5030 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
5032 SetLastError(CRYPT_E_ASN1_CORRUPT);
5033 ret = FALSE;
5035 TRACE("returning %d\n", ret);
5036 return ret;
5039 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
5040 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5041 DWORD *pcbDecoded)
5043 CMSG_SIGNER_INFO *info = pvStructInfo;
5044 struct AsnDecodeSequenceItem items[] = {
5045 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
5046 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5047 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
5048 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
5049 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
5050 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
5051 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5052 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5053 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5054 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
5055 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5056 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5057 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
5058 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5059 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
5060 HashEncryptionAlgorithm.pszObjId), 0 },
5061 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
5062 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5063 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
5064 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5065 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
5066 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5067 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5069 BOOL ret;
5071 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5072 pvStructInfo, *pcbStructInfo);
5074 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5075 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5076 pcbDecoded, info ? info->Issuer.pbData : NULL);
5077 return ret;
5080 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
5081 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5082 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5084 BOOL ret = FALSE;
5086 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5087 pDecodePara, pvStructInfo, *pcbStructInfo);
5089 __TRY
5091 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
5092 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5093 if (ret && pvStructInfo)
5095 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5096 pcbStructInfo, *pcbStructInfo);
5097 if (ret)
5099 CMSG_SIGNER_INFO *info;
5101 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5102 pvStructInfo = *(BYTE **)pvStructInfo;
5103 info = pvStructInfo;
5104 info->Issuer.pbData = ((BYTE *)info +
5105 sizeof(CMSG_SIGNER_INFO));
5106 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
5107 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5108 pcbStructInfo, NULL);
5112 __EXCEPT_PAGE_FAULT
5114 SetLastError(STATUS_ACCESS_VIOLATION);
5116 __ENDTRY
5117 TRACE("returning %d\n", ret);
5118 return ret;
5121 static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
5122 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5123 DWORD *pcbDecoded)
5125 BOOL ret;
5126 struct AsnArrayDescriptor arrayDesc = { 0,
5127 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
5128 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded),
5129 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded),
5130 CRYPT_AsnDecodeCopyBytes,
5131 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5133 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5134 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5136 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5137 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5138 return ret;
5141 static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
5142 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5143 DWORD *pcbDecoded)
5145 BOOL ret;
5146 struct AsnArrayDescriptor arrayDesc = { 0,
5147 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded),
5148 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded),
5149 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content),
5150 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB),
5151 TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5153 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5154 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5156 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5157 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5158 return ret;
5161 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
5162 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5163 DWORD *pcbDecoded)
5165 CERT_ID *id = pvStructInfo;
5166 BOOL ret = FALSE;
5168 if (*pbEncoded == ASN_SEQUENCEOF)
5170 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
5171 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
5172 if (ret)
5174 if (id)
5175 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5176 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
5177 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5178 sizeof(CERT_ISSUER_SERIAL_NUMBER);
5179 else
5180 *pcbStructInfo = sizeof(CERT_ID);
5183 else if (*pbEncoded == (ASN_CONTEXT | 0))
5185 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
5186 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
5187 if (ret)
5189 if (id)
5190 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
5191 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
5192 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5193 sizeof(CRYPT_DATA_BLOB);
5194 else
5195 *pcbStructInfo = sizeof(CERT_ID);
5198 else
5199 SetLastError(CRYPT_E_ASN1_BADTAG);
5200 return ret;
5203 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5204 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5205 DWORD *pcbDecoded)
5207 CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
5208 struct AsnDecodeSequenceItem items[] = {
5209 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5210 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5211 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5212 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5213 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
5214 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5215 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5216 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5217 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5218 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5219 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5220 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5221 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5222 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5223 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5224 HashEncryptionAlgorithm.pszObjId), 0 },
5225 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5226 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5227 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5228 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5229 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5230 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5231 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5233 BOOL ret;
5235 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5236 pvStructInfo, *pcbStructInfo);
5238 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5239 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5240 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
5241 return ret;
5244 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5245 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5246 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5248 BOOL ret = FALSE;
5250 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5251 pDecodePara, pvStructInfo, *pcbStructInfo);
5253 __TRY
5255 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5256 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5257 if (ret && pvStructInfo)
5259 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5260 pcbStructInfo, *pcbStructInfo);
5261 if (ret)
5263 CMSG_CMS_SIGNER_INFO *info;
5265 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5266 pvStructInfo = *(BYTE **)pvStructInfo;
5267 info = pvStructInfo;
5268 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
5269 sizeof(CMSG_CMS_SIGNER_INFO));
5270 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5271 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5272 pcbStructInfo, NULL);
5276 __EXCEPT_PAGE_FAULT
5278 SetLastError(STATUS_ACCESS_VIOLATION);
5280 __ENDTRY
5281 TRACE("returning %d\n", ret);
5282 return ret;
5285 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5286 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5288 BOOL ret;
5289 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5290 offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5291 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo),
5292 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo),
5293 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5294 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
5296 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5297 pvStructInfo, *pcbStructInfo, pcbDecoded);
5299 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5300 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5301 return ret;
5304 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5305 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5306 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5308 BOOL ret = FALSE;
5309 struct AsnDecodeSequenceItem items[] = {
5310 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5311 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5312 /* Placeholder for the hash algorithms - redundant with those in the
5313 * signers, so just ignore them.
5315 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5316 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5317 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5318 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5319 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5320 offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
5321 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
5322 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5323 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5324 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
5325 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
5326 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5327 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5328 CRYPT_DecodeSignerArray,
5329 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE,
5330 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5333 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5334 pDecodePara, signedInfo, *pcbSignedInfo);
5336 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5337 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5338 NULL, NULL);
5339 TRACE("returning %d\n", ret);
5340 return ret;
5343 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
5344 LPCSTR lpszStructType)
5346 CryptDecodeObjectExFunc decodeFunc = NULL;
5348 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
5349 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
5351 SetLastError(ERROR_FILE_NOT_FOUND);
5352 return NULL;
5354 if (!HIWORD(lpszStructType))
5356 switch (LOWORD(lpszStructType))
5358 case LOWORD(X509_CERT):
5359 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
5360 break;
5361 case LOWORD(X509_CERT_TO_BE_SIGNED):
5362 decodeFunc = CRYPT_AsnDecodeCert;
5363 break;
5364 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
5365 decodeFunc = CRYPT_AsnDecodeCRL;
5366 break;
5367 case LOWORD(X509_EXTENSIONS):
5368 decodeFunc = CRYPT_AsnDecodeExtensions;
5369 break;
5370 case LOWORD(X509_NAME_VALUE):
5371 decodeFunc = CRYPT_AsnDecodeNameValue;
5372 break;
5373 case LOWORD(X509_NAME):
5374 decodeFunc = CRYPT_AsnDecodeName;
5375 break;
5376 case LOWORD(X509_PUBLIC_KEY_INFO):
5377 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
5378 break;
5379 case LOWORD(X509_AUTHORITY_KEY_ID):
5380 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5381 break;
5382 case LOWORD(X509_ALTERNATE_NAME):
5383 decodeFunc = CRYPT_AsnDecodeAltName;
5384 break;
5385 case LOWORD(X509_BASIC_CONSTRAINTS):
5386 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5387 break;
5388 case LOWORD(X509_BASIC_CONSTRAINTS2):
5389 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5390 break;
5391 case LOWORD(X509_CERT_POLICIES):
5392 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5393 break;
5394 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
5395 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
5396 break;
5397 case LOWORD(X509_UNICODE_NAME):
5398 decodeFunc = CRYPT_AsnDecodeUnicodeName;
5399 break;
5400 case LOWORD(PKCS_ATTRIBUTE):
5401 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
5402 break;
5403 case LOWORD(X509_UNICODE_NAME_VALUE):
5404 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
5405 break;
5406 case LOWORD(X509_OCTET_STRING):
5407 decodeFunc = CRYPT_AsnDecodeOctets;
5408 break;
5409 case LOWORD(X509_BITS):
5410 case LOWORD(X509_KEY_USAGE):
5411 decodeFunc = CRYPT_AsnDecodeBits;
5412 break;
5413 case LOWORD(X509_INTEGER):
5414 decodeFunc = CRYPT_AsnDecodeInt;
5415 break;
5416 case LOWORD(X509_MULTI_BYTE_INTEGER):
5417 decodeFunc = CRYPT_AsnDecodeInteger;
5418 break;
5419 case LOWORD(X509_MULTI_BYTE_UINT):
5420 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
5421 break;
5422 case LOWORD(X509_ENUMERATED):
5423 decodeFunc = CRYPT_AsnDecodeEnumerated;
5424 break;
5425 case LOWORD(X509_CHOICE_OF_TIME):
5426 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
5427 break;
5428 case LOWORD(X509_AUTHORITY_KEY_ID2):
5429 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5430 break;
5431 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
5432 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5433 break;
5434 case LOWORD(PKCS_CONTENT_INFO):
5435 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
5436 break;
5437 case LOWORD(X509_SEQUENCE_OF_ANY):
5438 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
5439 break;
5440 case LOWORD(PKCS_UTC_TIME):
5441 decodeFunc = CRYPT_AsnDecodeUtcTime;
5442 break;
5443 case LOWORD(X509_CRL_DIST_POINTS):
5444 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5445 break;
5446 case LOWORD(X509_ENHANCED_KEY_USAGE):
5447 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5448 break;
5449 case LOWORD(PKCS_CTL):
5450 decodeFunc = CRYPT_AsnDecodeCTL;
5451 break;
5452 case LOWORD(PKCS_SMIME_CAPABILITIES):
5453 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5454 break;
5455 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
5456 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5457 break;
5458 case LOWORD(PKCS_ATTRIBUTES):
5459 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
5460 break;
5461 case LOWORD(X509_ISSUING_DIST_POINT):
5462 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5463 break;
5464 case LOWORD(X509_NAME_CONSTRAINTS):
5465 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5466 break;
5467 case LOWORD(PKCS7_SIGNER_INFO):
5468 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
5469 break;
5470 case LOWORD(CMS_SIGNER_INFO):
5471 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
5472 break;
5475 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
5476 decodeFunc = CRYPT_AsnDecodeExtensions;
5477 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
5478 decodeFunc = CRYPT_AsnDecodeUtcTime;
5479 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
5480 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5481 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
5482 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5483 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
5484 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5485 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
5486 decodeFunc = CRYPT_AsnDecodeEnumerated;
5487 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
5488 decodeFunc = CRYPT_AsnDecodeBits;
5489 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
5490 decodeFunc = CRYPT_AsnDecodeOctets;
5491 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
5492 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5493 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
5494 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5495 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
5496 decodeFunc = CRYPT_AsnDecodeAltName;
5497 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
5498 decodeFunc = CRYPT_AsnDecodeAltName;
5499 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
5500 decodeFunc = CRYPT_AsnDecodeAltName;
5501 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
5502 decodeFunc = CRYPT_AsnDecodeAltName;
5503 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
5504 decodeFunc = CRYPT_AsnDecodeAltName;
5505 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
5506 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5507 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
5508 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5509 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
5510 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5511 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
5512 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5513 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
5514 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5515 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
5516 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5517 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
5518 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5519 else if (!strcmp(lpszStructType, szOID_CTL))
5520 decodeFunc = CRYPT_AsnDecodeCTL;
5521 return decodeFunc;
5524 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
5525 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5527 static HCRYPTOIDFUNCSET set = NULL;
5528 CryptDecodeObjectFunc decodeFunc = NULL;
5530 if (!set)
5531 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
5532 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5533 (void **)&decodeFunc, hFunc);
5534 return decodeFunc;
5537 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
5538 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5540 static HCRYPTOIDFUNCSET set = NULL;
5541 CryptDecodeObjectExFunc decodeFunc = NULL;
5543 if (!set)
5544 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
5545 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5546 (void **)&decodeFunc, hFunc);
5547 return decodeFunc;
5550 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5551 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
5552 DWORD *pcbStructInfo)
5554 BOOL ret = FALSE;
5555 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
5556 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
5557 HCRYPTOIDFUNCADDR hFunc = NULL;
5559 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
5560 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
5561 pvStructInfo, pcbStructInfo);
5563 if (!pvStructInfo && !pcbStructInfo)
5565 SetLastError(ERROR_INVALID_PARAMETER);
5566 return FALSE;
5568 if (cbEncoded > MAX_ENCODED_LEN)
5570 SetLastError(CRYPT_E_ASN1_LARGE);
5571 return FALSE;
5574 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
5575 lpszStructType)))
5577 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5578 debugstr_a(lpszStructType));
5579 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
5580 lpszStructType, &hFunc);
5581 if (!pCryptDecodeObject)
5582 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
5583 lpszStructType, &hFunc);
5585 if (pCryptDecodeObject)
5586 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5587 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5588 else if (pCryptDecodeObjectEx)
5589 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
5590 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
5591 pvStructInfo, pcbStructInfo);
5592 if (hFunc)
5593 CryptFreeOIDFunctionAddress(hFunc, 0);
5594 TRACE_(crypt)("returning %d\n", ret);
5595 return ret;
5598 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5599 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5600 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5602 BOOL ret = FALSE;
5603 CryptDecodeObjectExFunc decodeFunc;
5604 HCRYPTOIDFUNCADDR hFunc = NULL;
5606 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
5607 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5608 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5610 if (!pvStructInfo && !pcbStructInfo)
5612 SetLastError(ERROR_INVALID_PARAMETER);
5613 return FALSE;
5615 if (cbEncoded > MAX_ENCODED_LEN)
5617 SetLastError(CRYPT_E_ASN1_LARGE);
5618 return FALSE;
5621 SetLastError(NOERROR);
5622 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5623 *(BYTE **)pvStructInfo = NULL;
5624 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
5625 if (!decodeFunc)
5627 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5628 debugstr_a(lpszStructType));
5629 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
5630 &hFunc);
5632 if (decodeFunc)
5633 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5634 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5635 else
5637 CryptDecodeObjectFunc pCryptDecodeObject =
5638 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
5640 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
5641 * directly, as that could cause an infinite loop.
5643 if (pCryptDecodeObject)
5645 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5647 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5648 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
5649 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5650 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
5651 ret = pCryptDecodeObject(dwCertEncodingType,
5652 lpszStructType, pbEncoded, cbEncoded, dwFlags,
5653 *(BYTE **)pvStructInfo, pcbStructInfo);
5655 else
5656 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5657 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5660 if (hFunc)
5661 CryptFreeOIDFunctionAddress(hFunc, 0);
5662 TRACE_(crypt)("returning %d\n", ret);
5663 return ret;
5666 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
5668 BOOL ret;
5670 TRACE_(crypt)("(%p)\n", pPFX);
5672 /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
5673 * version integer of length 1 (3 encoded byes) and at least one other
5674 * datum (two encoded bytes), plus at least two bytes for the outer
5675 * sequence. Thus, even an empty PFX blob is at least 7 bytes in length.
5677 if (pPFX->cbData < 7)
5678 ret = FALSE;
5679 else if (pPFX->pbData[0] == ASN_SEQUENCE)
5681 DWORD len;
5683 if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
5685 BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
5687 /* Need at least three bytes for the integer version */
5688 if (pPFX->cbData < 1 + lenLen + 3)
5689 ret = FALSE;
5690 else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
5691 pPFX->pbData[1 + lenLen + 1] != 1 || /* Definite length */
5692 pPFX->pbData[1 + lenLen + 2] != 3) /* PFX version */
5693 ret = FALSE;
5696 else
5697 ret = FALSE;
5698 return ret;
5701 HCERTSTORE WINAPI PFXImportCertStore(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword,
5702 DWORD dwFlags)
5704 FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags);
5705 return NULL;