crypt32: Pass next data pointer when decoding a CRL dist point.
[wine/wine64.git] / dlls / crypt32 / decode.c
blob84b08e714986ac562188fd26c115988ad5ac2133
1 /*
2 * Copyright 2005-2008 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 struct GenericArray
63 DWORD cItems;
64 BYTE *rgItems;
67 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
68 DWORD, DWORD, void *, DWORD *);
69 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
70 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
72 /* Internal decoders don't do memory allocation or exception handling, and
73 * they report how many bytes they decoded.
75 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
76 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
78 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
79 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
80 DWORD *pcbDecoded);
81 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
82 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
83 DWORD *pcbDecoded);
84 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
85 * time, doesn't do memory allocation, and doesn't do exception handling.
87 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
88 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
89 DWORD *pcbDecoded);
90 /* Assumes algo->Parameters.pbData is set ahead of time. */
91 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
92 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
93 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
94 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
97 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
98 DWORD *pcbDecoded);
99 /* Doesn't check the tag, assumes the caller does so */
100 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
101 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
102 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
103 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
104 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
105 * member has been initialized, doesn't do exception handling, and doesn't do
106 * memory allocation. Also doesn't check tag, assumes the caller has checked
107 * it.
109 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
110 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
111 DWORD *pcbDecoded);
112 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
113 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
114 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
115 DWORD *pcbDecoded);
116 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
117 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
118 DWORD *pcbDecoded);
120 /* Gets the number of length bytes from the given (leading) length byte */
121 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
123 /* Helper function to get the encoded length of the data starting at pbEncoded,
124 * where pbEncoded[0] is the tag. If the data are too short to contain a
125 * length or if the length is too large for cbEncoded, sets an appropriate
126 * error code and returns FALSE. If the encoded length is unknown due to
127 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
129 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
130 DWORD *len)
132 BOOL ret;
134 if (cbEncoded <= 1)
136 SetLastError(CRYPT_E_ASN1_CORRUPT);
137 ret = FALSE;
139 else if (pbEncoded[1] <= 0x7f)
141 if (pbEncoded[1] + 1 > cbEncoded)
143 SetLastError(CRYPT_E_ASN1_EOD);
144 ret = FALSE;
146 else
148 *len = pbEncoded[1];
149 ret = TRUE;
152 else if (pbEncoded[1] == 0x80)
154 *len = CMSG_INDEFINITE_LENGTH;
155 ret = TRUE;
157 else
159 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
161 if (lenLen > sizeof(DWORD) + 1)
163 SetLastError(CRYPT_E_ASN1_LARGE);
164 ret = FALSE;
166 else if (lenLen + 2 > cbEncoded)
168 SetLastError(CRYPT_E_ASN1_CORRUPT);
169 ret = FALSE;
171 else
173 DWORD out = 0;
175 pbEncoded += 2;
176 while (--lenLen)
178 out <<= 8;
179 out |= *pbEncoded++;
181 if (out + lenLen + 1 > cbEncoded)
183 SetLastError(CRYPT_E_ASN1_EOD);
184 ret = FALSE;
186 else
188 *len = out;
189 ret = TRUE;
193 return ret;
196 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
197 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
199 BOOL ret;
201 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
202 *len == CMSG_INDEFINITE_LENGTH)
204 SetLastError(CRYPT_E_ASN1_CORRUPT);
205 ret = FALSE;
207 return ret;
210 /* Helper function to check *pcbStructInfo, set it to the required size, and
211 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
212 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
213 * pointer to the newly allocated memory.
215 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
216 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
217 DWORD bytesNeeded)
219 BOOL ret = TRUE;
221 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
223 if (pDecodePara && pDecodePara->pfnAlloc)
224 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
225 else
226 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
227 if (!*(BYTE **)pvStructInfo)
228 ret = FALSE;
229 else
230 *pcbStructInfo = bytesNeeded;
232 else if (*pcbStructInfo < bytesNeeded)
234 *pcbStructInfo = bytesNeeded;
235 SetLastError(ERROR_MORE_DATA);
236 ret = FALSE;
238 else
239 *pcbStructInfo = bytesNeeded;
240 return ret;
243 static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
245 if (pDecodePara && pDecodePara->pfnFree)
246 pDecodePara->pfnFree(pv);
247 else
248 LocalFree(pv);
251 /* Helper function to check *pcbStructInfo and set it to the required size.
252 * Assumes pvStructInfo is not NULL.
254 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
256 BOOL ret;
258 if (*pcbStructInfo < bytesNeeded)
260 *pcbStructInfo = bytesNeeded;
261 SetLastError(ERROR_MORE_DATA);
262 ret = FALSE;
264 else
266 *pcbStructInfo = bytesNeeded;
267 ret = TRUE;
269 return ret;
272 /* tag:
273 * The expected tag of the item. If tag is 0, decodeFunc is called
274 * regardless of the tag value seen.
275 * offset:
276 * A sequence is decoded into a struct. The offset member is the
277 * offset of this item within that struct.
278 * decodeFunc:
279 * The decoder function to use. If this is NULL, then the member isn't
280 * decoded, but minSize space is reserved for it.
281 * minSize:
282 * The minimum amount of space occupied after decoding. You must set this.
283 * optional:
284 * If true, and the tag doesn't match the expected tag for this item,
285 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
286 * filled with 0 for this member.
287 * hasPointer, pointerOffset:
288 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
289 * the offset within the struct of the data pointer (or to the
290 * first data pointer, if more than one exist).
291 * size:
292 * Used by CRYPT_AsnDecodeSequence, not for your use.
294 struct AsnDecodeSequenceItem
296 BYTE tag;
297 DWORD offset;
298 InternalDecodeFunc decodeFunc;
299 DWORD minSize;
300 BOOL optional;
301 BOOL hasPointer;
302 DWORD pointerOffset;
303 DWORD size;
306 /* Decodes the items in a sequence, where the items are described in items,
307 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
308 * pvStructInfo. nextData is a pointer to the memory location at which the
309 * first decoded item with a dynamic pointer should point.
310 * Upon decoding, *cbDecoded is the total number of bytes decoded.
311 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
313 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
314 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
315 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
317 BOOL ret;
318 DWORD i, decoded = 0;
319 const BYTE *ptr = pbEncoded;
321 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
322 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
324 for (i = 0, ret = TRUE; ret && i < cItem; i++)
326 if (cbEncoded - (ptr - pbEncoded) != 0)
328 DWORD itemLen;
330 if ((ret = CRYPT_GetLengthIndefinite(ptr,
331 cbEncoded - (ptr - pbEncoded), &itemLen)))
333 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
335 if (ptr[0] == items[i].tag || !items[i].tag)
337 DWORD itemEncodedLen;
339 if (itemLen == CMSG_INDEFINITE_LENGTH)
340 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
341 else
342 itemEncodedLen = 1 + itemLenBytes + itemLen;
343 if (nextData && pvStructInfo && items[i].hasPointer)
345 TRACE("Setting next pointer to %p\n",
346 nextData);
347 *(BYTE **)((BYTE *)pvStructInfo +
348 items[i].pointerOffset) = nextData;
350 if (items[i].decodeFunc)
352 DWORD itemDecoded;
354 if (pvStructInfo)
355 TRACE("decoding item %d\n", i);
356 else
357 TRACE("sizing item %d\n", i);
358 ret = items[i].decodeFunc(ptr, itemEncodedLen,
359 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
360 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
361 : NULL, &items[i].size, &itemDecoded);
362 if (ret)
364 /* Account for alignment padding */
365 items[i].size = ALIGN_DWORD_PTR(items[i].size);
366 TRACE("item %d size: %d\n", i, items[i].size);
367 if (nextData && items[i].hasPointer &&
368 items[i].size > items[i].minSize)
369 nextData += items[i].size - items[i].minSize;
370 if (itemDecoded > itemEncodedLen)
372 WARN("decoded length %d exceeds encoded %d\n",
373 itemDecoded, itemEncodedLen);
374 SetLastError(CRYPT_E_ASN1_CORRUPT);
375 ret = FALSE;
377 else
379 if (itemLen == CMSG_INDEFINITE_LENGTH)
381 if (itemDecoded > itemEncodedLen - 2 ||
382 *(ptr + itemDecoded) != 0 ||
383 *(ptr + itemDecoded + 1) != 0)
385 TRACE("expected 0 TLV\n");
386 SetLastError(CRYPT_E_ASN1_CORRUPT);
387 ret = FALSE;
389 else
390 itemDecoded += 2;
392 if (ret)
394 ptr += itemDecoded;
395 decoded += itemDecoded;
396 TRACE("item %d: decoded %d bytes\n", i,
397 itemDecoded);
401 else if (items[i].optional &&
402 GetLastError() == CRYPT_E_ASN1_BADTAG)
404 TRACE("skipping optional item %d\n", i);
405 items[i].size = items[i].minSize;
406 SetLastError(NOERROR);
407 ret = TRUE;
409 else
410 TRACE("item %d failed: %08x\n", i,
411 GetLastError());
413 else if (itemLen == CMSG_INDEFINITE_LENGTH)
415 ERR("can't use indefinite length encoding without a decoder\n");
416 SetLastError(CRYPT_E_ASN1_CORRUPT);
417 ret = FALSE;
419 else
421 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
422 ptr += itemEncodedLen;
423 decoded += itemEncodedLen;
424 items[i].size = items[i].minSize;
427 else if (items[i].optional)
429 TRACE("skipping optional item %d\n", i);
430 items[i].size = items[i].minSize;
432 else
434 TRACE("item %d: tag %02x doesn't match expected %02x\n",
435 i, ptr[0], items[i].tag);
436 SetLastError(CRYPT_E_ASN1_BADTAG);
437 ret = FALSE;
441 else if (items[i].optional)
443 TRACE("missing optional item %d, skipping\n", i);
444 items[i].size = items[i].minSize;
446 else
448 TRACE("not enough bytes for item %d, failing\n", i);
449 SetLastError(CRYPT_E_ASN1_CORRUPT);
450 ret = FALSE;
453 if (cbDecoded)
454 *cbDecoded = decoded;
455 TRACE("returning %d\n", ret);
456 return ret;
459 /* This decodes an arbitrary sequence into a contiguous block of memory
460 * (basically, a struct.) Each element being decoded is described by a struct
461 * AsnDecodeSequenceItem, see above.
462 * startingPointer is an optional pointer to the first place where dynamic
463 * data will be stored. If you know the starting offset, you may pass it
464 * here. Otherwise, pass NULL, and one will be inferred from the items.
466 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
467 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
468 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
469 DWORD *pcbDecoded, void *startingPointer)
471 BOOL ret;
473 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
474 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
475 startingPointer);
477 if (!cbEncoded)
479 SetLastError(CRYPT_E_ASN1_EOD);
480 return FALSE;
482 if (pbEncoded[0] == ASN_SEQUENCE)
484 DWORD dataLen;
486 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
488 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
489 const BYTE *ptr = pbEncoded + 1 + lenBytes;
490 BOOL indefinite = FALSE;
492 cbEncoded -= 1 + lenBytes;
493 if (dataLen == CMSG_INDEFINITE_LENGTH)
495 dataLen = cbEncoded;
496 indefinite = TRUE;
498 else if (cbEncoded < dataLen)
500 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
501 cbEncoded);
502 SetLastError(CRYPT_E_ASN1_CORRUPT);
503 ret = FALSE;
505 if (ret)
507 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
508 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
509 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
511 if (cbDecoded > cbEncoded - 2)
513 /* Not enough space for 0 TLV */
514 SetLastError(CRYPT_E_ASN1_CORRUPT);
515 ret = FALSE;
517 else if (*(ptr + cbDecoded) != 0 ||
518 *(ptr + cbDecoded + 1) != 0)
520 TRACE("expected 0 TLV\n");
521 SetLastError(CRYPT_E_ASN1_CORRUPT);
522 ret = FALSE;
524 else
525 cbDecoded += 2;
528 if (ret && !indefinite && cbDecoded != dataLen)
530 TRACE("expected %d decoded, got %d, failing\n", dataLen,
531 cbDecoded);
532 SetLastError(CRYPT_E_ASN1_CORRUPT);
533 ret = FALSE;
535 if (ret)
537 DWORD i, bytesNeeded = 0, structSize = 0;
539 for (i = 0; i < cItem; i++)
541 bytesNeeded += items[i].size;
542 structSize += items[i].minSize;
544 if (pcbDecoded)
545 *pcbDecoded = 1 + lenBytes + cbDecoded;
546 if (!pvStructInfo)
547 *pcbStructInfo = bytesNeeded;
548 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
549 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
551 BYTE *nextData;
553 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
554 pvStructInfo = *(BYTE **)pvStructInfo;
555 if (startingPointer)
556 nextData = (BYTE *)startingPointer;
557 else
558 nextData = (BYTE *)pvStructInfo + structSize;
559 memset(pvStructInfo, 0, structSize);
560 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
561 ptr, dataLen, dwFlags, pvStructInfo, nextData,
562 &cbDecoded);
563 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
564 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
569 else
571 SetLastError(CRYPT_E_ASN1_BADTAG);
572 ret = FALSE;
574 TRACE("returning %d (%08x)\n", ret, GetLastError());
575 return ret;
578 /* tag:
579 * The expected tag of the entire encoded array (usually a variant
580 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
581 * regardless of the tag seen.
582 * decodeFunc:
583 * used to decode each item in the array
584 * itemSize:
585 * is the minimum size of each decoded item
586 * hasPointer:
587 * indicates whether each item has a dynamic pointer
588 * pointerOffset:
589 * indicates the offset within itemSize at which the pointer exists
591 struct AsnArrayDescriptor
593 BYTE tag;
594 InternalDecodeFunc decodeFunc;
595 DWORD itemSize;
596 BOOL hasPointer;
597 DWORD pointerOffset;
600 struct AsnArrayItemSize
602 DWORD encodedLen;
603 DWORD size;
606 /* Decodes an array of like types into a struct GenericArray.
607 * The layout and decoding of the array are described by a struct
608 * AsnArrayDescriptor.
610 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
611 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
612 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
613 DWORD *pcbDecoded, void *startingPointer)
615 BOOL ret = TRUE;
617 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
618 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
619 startingPointer);
621 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
623 DWORD dataLen;
625 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
627 DWORD bytesNeeded, cItems = 0, decoded;
628 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
629 /* There can be arbitrarily many items, but there is often only one.
631 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
633 decoded = 1 + lenBytes;
634 bytesNeeded = sizeof(struct GenericArray);
635 if (dataLen)
637 const BYTE *ptr;
638 BOOL doneDecoding = FALSE;
640 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
642 if (dataLen == CMSG_INDEFINITE_LENGTH)
644 if (ptr[0] == 0)
646 doneDecoding = TRUE;
647 if (ptr[1] != 0)
649 SetLastError(CRYPT_E_ASN1_CORRUPT);
650 ret = FALSE;
652 else
653 decoded += 2;
656 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
657 doneDecoding = TRUE;
658 if (!doneDecoding)
660 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
662 /* Each item decoded may not tolerate extraneous bytes,
663 * so get the length of the next element if known.
665 if ((ret = CRYPT_GetLengthIndefinite(ptr,
666 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
668 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
669 itemEncoded = cbEncoded - (ptr - pbEncoded);
670 else
671 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
672 itemDataLen;
674 if (ret)
675 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
676 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
677 &itemDecoded);
678 if (ret)
680 cItems++;
681 if (itemSizes != &itemSize)
682 itemSizes = CryptMemRealloc(itemSizes,
683 cItems * sizeof(struct AsnArrayItemSize));
684 else if (cItems > 1)
686 itemSizes =
687 CryptMemAlloc(
688 cItems * sizeof(struct AsnArrayItemSize));
689 if (itemSizes)
690 memcpy(itemSizes, &itemSize,
691 sizeof(itemSize));
693 if (itemSizes)
695 decoded += itemDecoded;
696 itemSizes[cItems - 1].encodedLen = itemEncoded;
697 itemSizes[cItems - 1].size = size;
698 bytesNeeded += size;
699 ptr += itemEncoded;
701 else
702 ret = FALSE;
707 if (ret)
709 if (pcbDecoded)
710 *pcbDecoded = decoded;
711 if (!pvStructInfo)
712 *pcbStructInfo = bytesNeeded;
713 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
714 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
716 DWORD i;
717 BYTE *nextData;
718 const BYTE *ptr;
719 struct GenericArray *array;
721 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
722 pvStructInfo = *(BYTE **)pvStructInfo;
723 array = (struct GenericArray *)pvStructInfo;
724 array->cItems = cItems;
725 if (startingPointer)
726 array->rgItems = startingPointer;
727 else
728 array->rgItems = (BYTE *)array +
729 sizeof(struct GenericArray);
730 nextData = array->rgItems +
731 array->cItems * arrayDesc->itemSize;
732 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
733 i < cItems && ptr - pbEncoded - 1 - lenBytes <
734 dataLen; i++)
736 DWORD itemDecoded;
738 if (arrayDesc->hasPointer)
739 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
740 + arrayDesc->pointerOffset) = nextData;
741 ret = arrayDesc->decodeFunc(ptr,
742 itemSizes[i].encodedLen,
743 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
744 array->rgItems + i * arrayDesc->itemSize,
745 &itemSizes[i].size, &itemDecoded);
746 if (ret)
748 nextData += itemSizes[i].size - arrayDesc->itemSize;
749 ptr += itemDecoded;
752 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
753 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
756 if (itemSizes != &itemSize)
757 CryptMemFree(itemSizes);
760 else
762 SetLastError(CRYPT_E_ASN1_BADTAG);
763 ret = FALSE;
765 return ret;
768 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
769 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
770 * to CRYPT_E_ASN1_CORRUPT.
771 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
772 * set!
774 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
775 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
777 BOOL ret;
778 DWORD dataLen;
780 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
782 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
783 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
785 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
786 bytesNeeded += 1 + lenBytes + dataLen;
788 if (pcbDecoded)
789 *pcbDecoded = 1 + lenBytes + dataLen;
790 if (!pvStructInfo)
791 *pcbStructInfo = bytesNeeded;
792 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
794 CRYPT_DER_BLOB *blob;
796 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
797 pvStructInfo = *(BYTE **)pvStructInfo;
798 blob = (CRYPT_DER_BLOB *)pvStructInfo;
799 blob->cbData = 1 + lenBytes + dataLen;
800 if (blob->cbData)
802 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
803 blob->pbData = (BYTE *)pbEncoded;
804 else
806 assert(blob->pbData);
807 memcpy(blob->pbData, pbEncoded, blob->cbData);
810 else
812 SetLastError(CRYPT_E_ASN1_CORRUPT);
813 ret = FALSE;
817 return ret;
820 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
821 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
822 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
823 DWORD *pcbDecoded)
825 BOOL ret;
827 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
828 pvStructInfo, *pcbStructInfo, pcbDecoded);
830 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
831 * place.
833 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
834 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
835 pcbDecoded);
836 if (ret && pvStructInfo)
838 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
840 if (blob->cbData)
842 DWORD i;
843 BYTE temp;
845 for (i = 0; i < blob->cbData / 2; i++)
847 temp = blob->pbData[i];
848 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
849 blob->pbData[blob->cbData - i - 1] = temp;
853 TRACE("returning %d (%08x)\n", ret, GetLastError());
854 return ret;
857 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
858 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
859 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
861 BOOL ret = TRUE;
863 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
864 pDecodePara, pvStructInfo, *pcbStructInfo);
866 __TRY
868 struct AsnDecodeSequenceItem items[] = {
869 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
870 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
871 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
872 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
873 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
874 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
875 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
876 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
877 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
878 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
881 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
882 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
883 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
884 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
885 pcbStructInfo, NULL, NULL);
887 __EXCEPT_PAGE_FAULT
889 SetLastError(STATUS_ACCESS_VIOLATION);
890 ret = FALSE;
892 __ENDTRY
894 TRACE("Returning %d (%08x)\n", ret, GetLastError());
895 return ret;
898 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
899 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
901 BOOL ret;
902 DWORD dataLen;
904 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
906 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
908 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
909 dwFlags, pvStructInfo, pcbStructInfo, NULL);
910 if (pcbDecoded)
911 *pcbDecoded = 1 + lenBytes + dataLen;
913 return ret;
916 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
917 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
919 BOOL ret;
921 struct AsnDecodeSequenceItem items[] = {
922 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
923 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
924 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
925 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
928 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
929 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
930 pcbDecoded, NULL);
931 return ret;
934 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
935 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
936 DWORD *pcbDecoded)
938 BOOL ret;
939 DWORD dataLen;
941 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
943 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
945 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
946 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
947 if (ret && pcbDecoded)
948 *pcbDecoded = 1 + lenBytes + dataLen;
950 return ret;
953 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
954 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
955 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
957 BOOL ret = TRUE;
958 struct AsnDecodeSequenceItem items[] = {
959 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
960 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
961 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
962 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
963 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
964 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
965 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
966 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
967 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
968 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
969 Issuer.pbData) },
970 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
971 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
972 FALSE, 0 },
973 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
974 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
975 Subject.pbData) },
976 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
977 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
978 FALSE, TRUE, offsetof(CERT_INFO,
979 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
980 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
981 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
982 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
983 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
984 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
985 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
986 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
987 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
988 offsetof(CERT_INFO, rgExtension), 0 },
991 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
992 pDecodePara, pvStructInfo, *pcbStructInfo);
994 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
995 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
996 NULL, NULL);
997 if (ret && pvStructInfo)
999 CERT_INFO *info;
1001 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1002 info = *(CERT_INFO **)pvStructInfo;
1003 else
1004 info = (CERT_INFO *)pvStructInfo;
1005 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1006 !info->Subject.cbData)
1008 SetLastError(CRYPT_E_ASN1_CORRUPT);
1009 /* Don't need to deallocate, because it should have failed on the
1010 * first pass (and no memory was allocated.)
1012 ret = FALSE;
1016 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1017 return ret;
1020 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1021 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1022 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1024 BOOL ret = FALSE;
1026 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1027 pDecodePara, pvStructInfo, *pcbStructInfo);
1029 __TRY
1031 DWORD size = 0;
1033 /* Unless told not to, first try to decode it as a signed cert. */
1034 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1036 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1038 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1039 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1040 (BYTE *)&signedCert, &size);
1041 if (ret)
1043 size = 0;
1044 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1045 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1046 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1047 pvStructInfo, pcbStructInfo);
1048 LocalFree(signedCert);
1051 /* Failing that, try it as an unsigned cert */
1052 if (!ret)
1054 size = 0;
1055 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1056 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1057 pDecodePara, pvStructInfo, pcbStructInfo);
1060 __EXCEPT_PAGE_FAULT
1062 SetLastError(STATUS_ACCESS_VIOLATION);
1064 __ENDTRY
1066 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1067 return ret;
1070 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1071 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1073 BOOL ret;
1074 struct AsnDecodeSequenceItem items[] = {
1075 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1076 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1077 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1078 { 0, offsetof(CRL_ENTRY, RevocationDate),
1079 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1080 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1081 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1082 offsetof(CRL_ENTRY, rgExtension), 0 },
1084 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1086 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1087 *pcbStructInfo);
1089 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1090 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1091 entry ? entry->SerialNumber.pbData : NULL);
1092 if (ret && entry && !entry->SerialNumber.cbData)
1094 WARN("empty CRL entry serial number\n");
1095 SetLastError(CRYPT_E_ASN1_CORRUPT);
1096 ret = FALSE;
1098 return ret;
1101 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1102 * been set prior to calling.
1104 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1105 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1107 BOOL ret;
1108 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1109 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1110 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1111 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1113 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1114 pvStructInfo, *pcbStructInfo, pcbDecoded);
1116 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1117 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1118 entries ? entries->rgItems : NULL);
1119 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1120 return ret;
1123 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1124 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1125 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1127 struct AsnDecodeSequenceItem items[] = {
1128 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1129 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1130 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1131 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1132 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1133 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1134 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1135 Issuer.pbData) },
1136 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1137 sizeof(FILETIME), FALSE, FALSE, 0 },
1138 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1139 sizeof(FILETIME), TRUE, FALSE, 0 },
1140 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1141 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1142 offsetof(CRL_INFO, rgCRLEntry), 0 },
1143 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1144 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1145 offsetof(CRL_INFO, rgExtension), 0 },
1147 BOOL ret = TRUE;
1149 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1150 pDecodePara, pvStructInfo, *pcbStructInfo);
1152 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1153 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1154 NULL, NULL);
1156 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1157 return ret;
1160 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1161 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1162 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1164 BOOL ret = FALSE;
1166 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1167 pDecodePara, pvStructInfo, *pcbStructInfo);
1169 __TRY
1171 DWORD size = 0;
1173 /* Unless told not to, first try to decode it as a signed crl. */
1174 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1176 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1178 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1179 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1180 (BYTE *)&signedCrl, &size);
1181 if (ret)
1183 size = 0;
1184 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1185 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1186 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1187 pvStructInfo, pcbStructInfo);
1188 LocalFree(signedCrl);
1191 /* Failing that, try it as an unsigned crl */
1192 if (!ret)
1194 size = 0;
1195 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1196 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1197 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1200 __EXCEPT_PAGE_FAULT
1202 SetLastError(STATUS_ACCESS_VIOLATION);
1204 __ENDTRY
1206 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1207 return ret;
1210 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1211 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1213 BOOL ret = TRUE;
1214 DWORD dataLen;
1216 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1217 pvStructInfo, *pcbStructInfo);
1219 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1221 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1222 DWORD bytesNeeded = sizeof(LPSTR);
1224 if (dataLen)
1226 /* The largest possible string for the first two components
1227 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1229 char firstTwo[6];
1230 const BYTE *ptr;
1232 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1233 pbEncoded[1 + lenBytes] / 40,
1234 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1235 * 40);
1236 bytesNeeded += strlen(firstTwo) + 1;
1237 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1238 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1240 /* large enough for ".4000000" */
1241 char str[9];
1242 int val = 0;
1244 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1245 (*ptr & 0x80))
1247 val <<= 7;
1248 val |= *ptr & 0x7f;
1249 ptr++;
1251 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1252 (*ptr & 0x80))
1254 SetLastError(CRYPT_E_ASN1_CORRUPT);
1255 ret = FALSE;
1257 else
1259 val <<= 7;
1260 val |= *ptr++;
1261 snprintf(str, sizeof(str), ".%d", val);
1262 bytesNeeded += strlen(str);
1266 if (pcbDecoded)
1267 *pcbDecoded = 1 + lenBytes + dataLen;
1268 if (!pvStructInfo)
1269 *pcbStructInfo = bytesNeeded;
1270 else if (*pcbStructInfo < bytesNeeded)
1272 *pcbStructInfo = bytesNeeded;
1273 SetLastError(ERROR_MORE_DATA);
1274 ret = FALSE;
1276 else
1278 if (dataLen)
1280 const BYTE *ptr;
1281 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1283 *pszObjId = 0;
1284 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1285 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1286 40) * 40);
1287 pszObjId += strlen(pszObjId);
1288 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1289 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1291 int val = 0;
1293 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1294 (*ptr & 0x80))
1296 val <<= 7;
1297 val |= *ptr & 0x7f;
1298 ptr++;
1300 val <<= 7;
1301 val |= *ptr++;
1302 sprintf(pszObjId, ".%d", val);
1303 pszObjId += strlen(pszObjId);
1306 else
1307 *(LPSTR *)pvStructInfo = NULL;
1308 *pcbStructInfo = bytesNeeded;
1311 return ret;
1314 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1315 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1317 BOOL ret;
1319 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1320 pvStructInfo, *pcbStructInfo);
1322 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1323 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1324 pvStructInfo, pcbStructInfo, pcbDecoded);
1325 else
1327 SetLastError(CRYPT_E_ASN1_BADTAG);
1328 ret = FALSE;
1330 return ret;
1333 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1334 * ahead of time!
1336 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1337 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1339 struct AsnDecodeSequenceItem items[] = {
1340 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1341 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1342 offsetof(CERT_EXTENSION, pszObjId), 0 },
1343 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1344 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1345 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1346 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1347 offsetof(CERT_EXTENSION, Value.pbData) },
1349 BOOL ret = TRUE;
1350 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1352 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1353 *pcbStructInfo);
1355 if (ext)
1356 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1357 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1358 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1359 pcbDecoded, ext ? ext->pszObjId : NULL);
1360 if (ext)
1361 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1362 debugstr_a(ext->pszObjId));
1363 TRACE("returning %d (%08x)\n", ret, GetLastError());
1364 return ret;
1367 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1368 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1369 DWORD *pcbDecoded)
1371 BOOL ret = TRUE;
1372 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1373 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1374 offsetof(CERT_EXTENSION, pszObjId) };
1375 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1377 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1378 pvStructInfo, *pcbStructInfo, pcbDecoded);
1380 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1381 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1382 exts ? exts->rgExtension : NULL);
1383 return ret;
1386 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1387 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1388 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1390 BOOL ret = TRUE;
1392 __TRY
1394 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1395 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1396 if (ret && pvStructInfo)
1398 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1399 pcbStructInfo, *pcbStructInfo);
1400 if (ret)
1402 CERT_EXTENSIONS *exts;
1404 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1405 pvStructInfo = *(BYTE **)pvStructInfo;
1406 exts = (CERT_EXTENSIONS *)pvStructInfo;
1407 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1408 sizeof(CERT_EXTENSIONS));
1409 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1410 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1411 pcbStructInfo, NULL);
1415 __EXCEPT_PAGE_FAULT
1417 SetLastError(STATUS_ACCESS_VIOLATION);
1418 ret = FALSE;
1420 __ENDTRY
1421 return ret;
1424 /* Warning: this assumes the address of value->Value.pbData is already set, in
1425 * order to avoid overwriting memory. (In some cases, it may change it, if it
1426 * doesn't copy anything to memory.) Be sure to set it correctly!
1428 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1429 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1430 DWORD *pcbDecoded)
1432 BOOL ret = TRUE;
1433 DWORD dataLen;
1434 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1436 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1438 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1439 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1441 switch (pbEncoded[0])
1443 case ASN_OCTETSTRING:
1444 valueType = CERT_RDN_OCTET_STRING;
1445 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1446 bytesNeeded += dataLen;
1447 break;
1448 case ASN_NUMERICSTRING:
1449 valueType = CERT_RDN_NUMERIC_STRING;
1450 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1451 bytesNeeded += dataLen;
1452 break;
1453 case ASN_PRINTABLESTRING:
1454 valueType = CERT_RDN_PRINTABLE_STRING;
1455 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1456 bytesNeeded += dataLen;
1457 break;
1458 case ASN_IA5STRING:
1459 valueType = CERT_RDN_IA5_STRING;
1460 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1461 bytesNeeded += dataLen;
1462 break;
1463 case ASN_T61STRING:
1464 valueType = CERT_RDN_T61_STRING;
1465 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1466 bytesNeeded += dataLen;
1467 break;
1468 case ASN_VIDEOTEXSTRING:
1469 valueType = CERT_RDN_VIDEOTEX_STRING;
1470 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1471 bytesNeeded += dataLen;
1472 break;
1473 case ASN_GRAPHICSTRING:
1474 valueType = CERT_RDN_GRAPHIC_STRING;
1475 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1476 bytesNeeded += dataLen;
1477 break;
1478 case ASN_VISIBLESTRING:
1479 valueType = CERT_RDN_VISIBLE_STRING;
1480 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1481 bytesNeeded += dataLen;
1482 break;
1483 case ASN_GENERALSTRING:
1484 valueType = CERT_RDN_GENERAL_STRING;
1485 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1486 bytesNeeded += dataLen;
1487 break;
1488 case ASN_UNIVERSALSTRING:
1489 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1490 SetLastError(CRYPT_E_ASN1_BADTAG);
1491 return FALSE;
1492 case ASN_BMPSTRING:
1493 valueType = CERT_RDN_BMP_STRING;
1494 bytesNeeded += dataLen;
1495 break;
1496 case ASN_UTF8STRING:
1497 valueType = CERT_RDN_UTF8_STRING;
1498 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1499 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1500 break;
1501 default:
1502 SetLastError(CRYPT_E_ASN1_BADTAG);
1503 return FALSE;
1506 if (pcbDecoded)
1507 *pcbDecoded = 1 + lenBytes + dataLen;
1508 if (!value)
1509 *pcbStructInfo = bytesNeeded;
1510 else if (*pcbStructInfo < bytesNeeded)
1512 *pcbStructInfo = bytesNeeded;
1513 SetLastError(ERROR_MORE_DATA);
1514 ret = FALSE;
1516 else
1518 *pcbStructInfo = bytesNeeded;
1519 value->dwValueType = valueType;
1520 if (dataLen)
1522 DWORD i;
1524 assert(value->Value.pbData);
1525 switch (pbEncoded[0])
1527 case ASN_OCTETSTRING:
1528 case ASN_NUMERICSTRING:
1529 case ASN_PRINTABLESTRING:
1530 case ASN_IA5STRING:
1531 case ASN_T61STRING:
1532 case ASN_VIDEOTEXSTRING:
1533 case ASN_GRAPHICSTRING:
1534 case ASN_VISIBLESTRING:
1535 case ASN_GENERALSTRING:
1536 value->Value.cbData = dataLen;
1537 if (dataLen)
1539 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1540 memcpy(value->Value.pbData,
1541 pbEncoded + 1 + lenBytes, dataLen);
1542 else
1543 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1544 lenBytes;
1546 break;
1547 case ASN_BMPSTRING:
1549 LPWSTR str = (LPWSTR)value->Value.pbData;
1551 value->Value.cbData = dataLen;
1552 for (i = 0; i < dataLen / 2; i++)
1553 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1554 pbEncoded[1 + lenBytes + 2 * i + 1];
1555 break;
1557 case ASN_UTF8STRING:
1559 LPWSTR str = (LPWSTR)value->Value.pbData;
1561 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1562 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1563 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1564 break;
1568 else
1570 value->Value.cbData = 0;
1571 value->Value.pbData = NULL;
1575 return ret;
1578 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1579 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1580 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1582 BOOL ret = TRUE;
1584 __TRY
1586 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1587 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1588 if (ret && pvStructInfo)
1590 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1591 pcbStructInfo, *pcbStructInfo);
1592 if (ret)
1594 CERT_NAME_VALUE *value;
1596 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1597 pvStructInfo = *(BYTE **)pvStructInfo;
1598 value = (CERT_NAME_VALUE *)pvStructInfo;
1599 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1600 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1601 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1602 pcbStructInfo, NULL);
1606 __EXCEPT_PAGE_FAULT
1608 SetLastError(STATUS_ACCESS_VIOLATION);
1609 ret = FALSE;
1611 __ENDTRY
1612 return ret;
1615 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1616 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1617 DWORD *pcbDecoded)
1619 BOOL ret = TRUE;
1620 DWORD dataLen;
1621 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1623 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1625 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1626 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1628 switch (pbEncoded[0])
1630 case ASN_NUMERICSTRING:
1631 valueType = CERT_RDN_NUMERIC_STRING;
1632 if (dataLen)
1633 bytesNeeded += (dataLen + 1) * 2;
1634 break;
1635 case ASN_PRINTABLESTRING:
1636 valueType = CERT_RDN_PRINTABLE_STRING;
1637 if (dataLen)
1638 bytesNeeded += (dataLen + 1) * 2;
1639 break;
1640 case ASN_IA5STRING:
1641 valueType = CERT_RDN_IA5_STRING;
1642 if (dataLen)
1643 bytesNeeded += (dataLen + 1) * 2;
1644 break;
1645 case ASN_T61STRING:
1646 valueType = CERT_RDN_T61_STRING;
1647 if (dataLen)
1648 bytesNeeded += (dataLen + 1) * 2;
1649 break;
1650 case ASN_VIDEOTEXSTRING:
1651 valueType = CERT_RDN_VIDEOTEX_STRING;
1652 if (dataLen)
1653 bytesNeeded += (dataLen + 1) * 2;
1654 break;
1655 case ASN_GRAPHICSTRING:
1656 valueType = CERT_RDN_GRAPHIC_STRING;
1657 if (dataLen)
1658 bytesNeeded += (dataLen + 1) * 2;
1659 break;
1660 case ASN_VISIBLESTRING:
1661 valueType = CERT_RDN_VISIBLE_STRING;
1662 if (dataLen)
1663 bytesNeeded += (dataLen + 1) * 2;
1664 break;
1665 case ASN_GENERALSTRING:
1666 valueType = CERT_RDN_GENERAL_STRING;
1667 if (dataLen)
1668 bytesNeeded += (dataLen + 1) * 2;
1669 break;
1670 case ASN_UNIVERSALSTRING:
1671 valueType = CERT_RDN_UNIVERSAL_STRING;
1672 if (dataLen)
1673 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
1674 break;
1675 case ASN_BMPSTRING:
1676 valueType = CERT_RDN_BMP_STRING;
1677 if (dataLen)
1678 bytesNeeded += dataLen + sizeof(WCHAR);
1679 break;
1680 case ASN_UTF8STRING:
1681 valueType = CERT_RDN_UTF8_STRING;
1682 if (dataLen)
1683 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
1684 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
1685 break;
1686 default:
1687 SetLastError(CRYPT_E_ASN1_BADTAG);
1688 return FALSE;
1691 if (pcbDecoded)
1692 *pcbDecoded = 1 + lenBytes + dataLen;
1693 if (!value)
1694 *pcbStructInfo = bytesNeeded;
1695 else if (*pcbStructInfo < bytesNeeded)
1697 *pcbStructInfo = bytesNeeded;
1698 SetLastError(ERROR_MORE_DATA);
1699 ret = FALSE;
1701 else
1703 *pcbStructInfo = bytesNeeded;
1704 value->dwValueType = valueType;
1705 if (dataLen)
1707 DWORD i;
1708 LPWSTR str = (LPWSTR)value->Value.pbData;
1710 assert(value->Value.pbData);
1711 switch (pbEncoded[0])
1713 case ASN_NUMERICSTRING:
1714 case ASN_PRINTABLESTRING:
1715 case ASN_IA5STRING:
1716 case ASN_T61STRING:
1717 case ASN_VIDEOTEXSTRING:
1718 case ASN_GRAPHICSTRING:
1719 case ASN_VISIBLESTRING:
1720 case ASN_GENERALSTRING:
1721 value->Value.cbData = dataLen * 2;
1722 for (i = 0; i < dataLen; i++)
1723 str[i] = pbEncoded[1 + lenBytes + i];
1724 str[i] = 0;
1725 break;
1726 case ASN_UNIVERSALSTRING:
1727 value->Value.cbData = dataLen / 2;
1728 for (i = 0; i < dataLen / 4; i++)
1729 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1730 | pbEncoded[1 + lenBytes + 2 * i + 3];
1731 str[i] = 0;
1732 break;
1733 case ASN_BMPSTRING:
1734 value->Value.cbData = dataLen;
1735 for (i = 0; i < dataLen / 2; i++)
1736 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1737 pbEncoded[1 + lenBytes + 2 * i + 1];
1738 str[i] = 0;
1739 break;
1740 case ASN_UTF8STRING:
1741 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1742 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1743 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1744 value->Value.pbData[value->Value.cbData / sizeof(WCHAR)]
1745 = 0;
1746 value->Value.cbData += sizeof(WCHAR);
1747 break;
1750 else
1752 value->Value.cbData = 0;
1753 value->Value.pbData = NULL;
1757 return ret;
1760 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1761 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1762 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1764 BOOL ret = TRUE;
1766 __TRY
1768 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1769 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1770 if (ret && pvStructInfo)
1772 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1773 pcbStructInfo, *pcbStructInfo);
1774 if (ret)
1776 CERT_NAME_VALUE *value;
1778 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1779 pvStructInfo = *(BYTE **)pvStructInfo;
1780 value = (CERT_NAME_VALUE *)pvStructInfo;
1781 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1782 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1783 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1784 pcbStructInfo, NULL);
1788 __EXCEPT_PAGE_FAULT
1790 SetLastError(STATUS_ACCESS_VIOLATION);
1791 ret = FALSE;
1793 __ENDTRY
1794 return ret;
1797 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1798 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1800 BOOL ret;
1801 struct AsnDecodeSequenceItem items[] = {
1802 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1803 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1804 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1805 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1806 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1807 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1809 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1811 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1812 pvStructInfo, *pcbStructInfo);
1814 if (attr)
1815 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1816 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1817 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1818 attr ? attr->pszObjId : NULL);
1819 if (attr)
1821 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1822 debugstr_a(attr->pszObjId));
1823 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1825 TRACE("returning %d (%08x)\n", ret, GetLastError());
1826 return ret;
1829 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1830 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1832 BOOL ret = TRUE;
1833 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1834 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1835 offsetof(CERT_RDN_ATTR, pszObjId) };
1836 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1838 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1839 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1840 rdn ? rdn->rgRDNAttr : NULL);
1841 return ret;
1844 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1845 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1846 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1848 BOOL ret = TRUE;
1850 __TRY
1852 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1853 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1854 offsetof(CERT_RDN, rgRDNAttr) };
1856 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1857 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1859 __EXCEPT_PAGE_FAULT
1861 SetLastError(STATUS_ACCESS_VIOLATION);
1862 ret = FALSE;
1864 __ENDTRY
1865 return ret;
1868 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1869 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1870 DWORD *pcbDecoded)
1872 BOOL ret;
1873 struct AsnDecodeSequenceItem items[] = {
1874 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1875 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1876 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1877 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1878 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1879 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1881 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1883 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1884 pvStructInfo, *pcbStructInfo);
1886 if (attr)
1887 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1888 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1889 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1890 attr ? attr->pszObjId : NULL);
1891 if (attr)
1893 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1894 debugstr_a(attr->pszObjId));
1895 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1897 TRACE("returning %d (%08x)\n", ret, GetLastError());
1898 return ret;
1901 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1902 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1904 BOOL ret = TRUE;
1905 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1906 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1907 offsetof(CERT_RDN_ATTR, pszObjId) };
1908 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1910 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1911 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1912 rdn ? rdn->rgRDNAttr : NULL);
1913 return ret;
1916 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1917 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1918 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1920 BOOL ret = TRUE;
1922 __TRY
1924 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1925 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1926 offsetof(CERT_RDN, rgRDNAttr) };
1928 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1929 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1931 __EXCEPT_PAGE_FAULT
1933 SetLastError(STATUS_ACCESS_VIOLATION);
1934 ret = FALSE;
1936 __ENDTRY
1937 return ret;
1940 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1941 DWORD *pcbDecoded)
1943 BOOL ret = TRUE, done = FALSE;
1944 DWORD indefiniteNestingLevels = 0, decoded = 0;
1946 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1948 do {
1949 DWORD dataLen;
1951 if (!cbEncoded)
1952 done = TRUE;
1953 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
1954 &dataLen)))
1956 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1958 if (dataLen == CMSG_INDEFINITE_LENGTH)
1960 indefiniteNestingLevels++;
1961 pbEncoded += 1 + lenBytes;
1962 cbEncoded -= 1 + lenBytes;
1963 decoded += 1 + lenBytes;
1964 TRACE("indefiniteNestingLevels = %d\n",
1965 indefiniteNestingLevels);
1967 else
1969 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
1970 indefiniteNestingLevels)
1972 indefiniteNestingLevels--;
1973 TRACE("indefiniteNestingLevels = %d\n",
1974 indefiniteNestingLevels);
1976 pbEncoded += 1 + lenBytes + dataLen;
1977 cbEncoded -= 1 + lenBytes + dataLen;
1978 decoded += 1 + lenBytes + dataLen;
1979 if (!indefiniteNestingLevels)
1980 done = TRUE;
1983 } while (ret && !done);
1984 /* If we haven't found all 0 TLVs, we haven't found the end */
1985 if (ret && indefiniteNestingLevels)
1987 SetLastError(CRYPT_E_ASN1_EOD);
1988 ret = FALSE;
1990 if (ret)
1991 *pcbDecoded = decoded;
1992 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
1993 return ret;
1996 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1997 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1998 DWORD *pcbDecoded)
2000 BOOL ret = TRUE;
2001 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
2003 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2004 pvStructInfo, *pcbStructInfo);
2006 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
2008 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2009 bytesNeeded += encodedLen;
2010 if (!pvStructInfo)
2011 *pcbStructInfo = bytesNeeded;
2012 else if (*pcbStructInfo < bytesNeeded)
2014 SetLastError(ERROR_MORE_DATA);
2015 *pcbStructInfo = bytesNeeded;
2016 ret = FALSE;
2018 else
2020 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
2022 *pcbStructInfo = bytesNeeded;
2023 blob->cbData = encodedLen;
2024 if (encodedLen)
2026 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2027 blob->pbData = (LPBYTE)pbEncoded;
2028 else
2030 assert(blob->pbData);
2031 memcpy(blob->pbData, pbEncoded, blob->cbData);
2034 else
2035 blob->pbData = NULL;
2037 if (pcbDecoded)
2038 *pcbDecoded = encodedLen;
2040 return ret;
2043 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
2044 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2046 BOOL ret;
2047 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
2048 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2049 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
2051 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2052 pvStructInfo, *pcbStructInfo, pcbDecoded);
2054 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2055 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2056 array ? array->rgItems : NULL);
2057 return ret;
2060 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2061 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2063 BOOL ret;
2064 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2065 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2066 CTL_USAGE *usage = (CTL_USAGE *)pvStructInfo;
2068 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2069 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2070 usage ? usage->rgpszUsageIdentifier : NULL);
2071 return ret;
2074 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2075 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2077 struct AsnDecodeSequenceItem items[] = {
2078 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2079 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2080 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2081 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2082 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), FALSE,
2083 TRUE, offsetof(CTL_ENTRY, rgAttribute), 0 },
2085 BOOL ret = TRUE;
2086 CTL_ENTRY *entry = (CTL_ENTRY *)pvStructInfo;
2088 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2089 *pcbStructInfo);
2091 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2092 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2093 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2094 return ret;
2097 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2098 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2100 BOOL ret;
2101 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2102 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2103 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2104 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2106 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2107 pvStructInfo, *pcbStructInfo, pcbDecoded);
2109 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2110 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2111 entries ? entries->rgItems : NULL);
2112 return ret;
2115 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2116 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2117 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2119 BOOL ret = FALSE;
2121 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2122 pDecodePara, pvStructInfo, *pcbStructInfo);
2124 __TRY
2126 struct AsnDecodeSequenceItem items[] = {
2127 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2128 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2129 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2130 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2131 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2132 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2133 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
2134 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2135 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2136 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2137 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2138 { 0, offsetof(CTL_INFO, ThisUpdate),
2139 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2140 0 },
2141 { 0, offsetof(CTL_INFO, NextUpdate),
2142 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2143 0 },
2144 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2145 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2146 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2147 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2148 CRYPT_AsnDecodeCTLEntries, sizeof(struct GenericArray),
2149 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2150 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2151 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
2152 offsetof(CTL_INFO, rgExtension), 0 },
2155 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2156 pDecodePara, pvStructInfo, *pcbStructInfo);
2158 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2159 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2160 pcbStructInfo, NULL, NULL);
2162 __EXCEPT_PAGE_FAULT
2164 SetLastError(STATUS_ACCESS_VIOLATION);
2166 __ENDTRY
2167 return ret;
2170 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2171 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2172 DWORD *pcbDecoded)
2174 BOOL ret;
2175 struct AsnDecodeSequenceItem items[] = {
2176 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2177 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2178 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2179 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2180 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2181 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2183 PCRYPT_SMIME_CAPABILITY capability = (PCRYPT_SMIME_CAPABILITY)pvStructInfo;
2185 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2186 pvStructInfo, *pcbStructInfo);
2188 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2189 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2190 pcbDecoded, capability ? capability->pszObjId : NULL);
2191 TRACE("returning %d\n", ret);
2192 return ret;
2195 static BOOL CRYPT_AsnDecodeSMIMECapabilitiesInternal(const BYTE *pbEncoded,
2196 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2197 DWORD *pcbDecoded)
2199 struct AsnArrayDescriptor arrayDesc = { 0,
2200 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2201 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2202 PCRYPT_SMIME_CAPABILITIES capabilities =
2203 (PCRYPT_SMIME_CAPABILITIES)pvStructInfo;
2204 BOOL ret;
2206 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2207 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2208 capabilities ? capabilities->rgCapability : NULL);
2209 return ret;
2212 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2213 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2214 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2216 BOOL ret = FALSE;
2218 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2219 pDecodePara, pvStructInfo, *pcbStructInfo);
2221 __TRY
2223 DWORD bytesNeeded;
2225 if (!cbEncoded)
2226 SetLastError(CRYPT_E_ASN1_EOD);
2227 else if (pbEncoded[0] != ASN_SEQUENCEOF)
2228 SetLastError(CRYPT_E_ASN1_CORRUPT);
2229 else if ((ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
2230 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2231 NULL)))
2233 if (!pvStructInfo)
2234 *pcbStructInfo = bytesNeeded;
2235 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2236 pvStructInfo, pcbStructInfo, bytesNeeded)))
2238 PCRYPT_SMIME_CAPABILITIES capabilities;
2240 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2241 pvStructInfo = *(BYTE **)pvStructInfo;
2242 capabilities = (PCRYPT_SMIME_CAPABILITIES)pvStructInfo;
2243 capabilities->rgCapability =
2244 (PCRYPT_SMIME_CAPABILITY)((BYTE *)pvStructInfo +
2245 sizeof(CRYPT_SMIME_CAPABILITIES));
2246 ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
2247 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2248 &bytesNeeded, NULL);
2252 __EXCEPT_PAGE_FAULT
2254 SetLastError(STATUS_ACCESS_VIOLATION);
2256 __ENDTRY
2257 TRACE("returning %d\n", ret);
2258 return ret;
2261 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
2262 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2263 DWORD *pcbDecoded)
2265 BOOL ret = TRUE;
2266 DWORD dataLen;
2267 LPSTR *pStr = pvStructInfo;
2269 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2271 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2272 DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
2274 if (pbEncoded[0] != ASN_IA5STRING)
2276 SetLastError(CRYPT_E_ASN1_CORRUPT);
2277 ret = FALSE;
2279 else
2281 bytesNeeded += dataLen;
2282 if (pcbDecoded)
2283 *pcbDecoded = 1 + lenBytes + dataLen;
2284 if (!pvStructInfo)
2285 *pcbStructInfo = bytesNeeded;
2286 else if (*pcbStructInfo < bytesNeeded)
2288 *pcbStructInfo = bytesNeeded;
2289 SetLastError(ERROR_MORE_DATA);
2290 ret = FALSE;
2292 else
2294 *pcbStructInfo = bytesNeeded;
2295 if (dataLen)
2297 LPSTR str = *pStr;
2299 assert(str);
2300 memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
2301 str[dataLen] = 0;
2303 else
2304 *pStr = NULL;
2308 return ret;
2311 static BOOL CRYPT_AsnDecodeIntArray(const BYTE *pbEncoded,
2312 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2313 DWORD *pcbDecoded)
2315 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2316 CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
2317 struct GenericArray *array = pvStructInfo;
2318 BOOL ret;
2320 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2321 pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
2323 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2324 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2325 array ? array->rgItems : NULL);
2326 TRACE("returning %d\n", ret);
2327 return ret;
2330 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
2331 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2332 DWORD *pcbDecoded)
2334 BOOL ret;
2335 struct AsnDecodeSequenceItem items[] = {
2336 { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2337 pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
2338 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
2339 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2340 cNoticeNumbers), CRYPT_AsnDecodeIntArray, sizeof(struct GenericArray),
2341 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2342 rgNoticeNumbers), 0 },
2344 DWORD bytesNeeded;
2346 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2347 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2349 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2350 pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
2351 NULL);
2352 if (ret)
2354 /* The caller is expecting a pointer to a
2355 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
2356 * CRYPT_AsnDecodeSequence is decoding a
2357 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. Increment the bytes
2358 * needed, and decode again if the requisite space is available.
2360 bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
2361 if (!pvStructInfo)
2362 *pcbStructInfo = bytesNeeded;
2363 else if (*pcbStructInfo < bytesNeeded)
2365 *pcbStructInfo = bytesNeeded;
2366 SetLastError(ERROR_MORE_DATA);
2367 ret = FALSE;
2369 else
2371 PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
2373 *pcbStructInfo = bytesNeeded;
2374 /* The pointer (pvStructInfo) passed in points to the first dynamic
2375 * pointer, so use it as the pointer to the
2376 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
2377 * appropriate offset for the first dynamic pointer within the
2378 * notice reference by pointing to the first memory location past
2379 * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
2381 noticeRef =
2382 *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
2383 noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
2384 sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
2385 ret = CRYPT_AsnDecodeSequence(items,
2386 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2387 NULL, noticeRef, &bytesNeeded, pcbDecoded,
2388 noticeRef->pszOrganization);
2391 TRACE("returning %d\n", ret);
2392 return ret;
2395 static BOOL CRYPT_AsnDecodeBMPString(const BYTE *pbEncoded,
2396 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2397 DWORD *pcbDecoded)
2399 BOOL ret = TRUE;
2400 DWORD dataLen;
2401 LPWSTR *pStr = pvStructInfo;
2403 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2405 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2406 DWORD bytesNeeded = sizeof(LPWSTR) + sizeof(WCHAR);
2408 if (pbEncoded[0] != ASN_BMPSTRING)
2410 SetLastError(CRYPT_E_ASN1_CORRUPT);
2411 ret = FALSE;
2413 else
2415 bytesNeeded += dataLen;
2416 if (pcbDecoded)
2417 *pcbDecoded = 1 + lenBytes + dataLen;
2418 if (!pvStructInfo)
2419 *pcbStructInfo = bytesNeeded;
2420 else if (*pcbStructInfo < bytesNeeded)
2422 *pcbStructInfo = bytesNeeded;
2423 SetLastError(ERROR_MORE_DATA);
2424 ret = FALSE;
2426 else
2428 *pcbStructInfo = bytesNeeded;
2429 if (dataLen)
2431 DWORD i;
2432 LPWSTR str = *pStr;
2434 assert(str);
2435 for (i = 0; i < dataLen / 2; i++)
2436 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2437 pbEncoded[1 + lenBytes + 2 * i + 1];
2438 str[i] = 0;
2440 else
2441 *pStr = NULL;
2445 return ret;
2448 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2449 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2450 DWORD *pcbStructInfo, DWORD *pcbDecoded)
2452 BOOL ret;
2453 struct AsnDecodeSequenceItem items[] = {
2454 { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2455 pNoticeReference), CRYPT_AsnDecodeNoticeReference,
2456 sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
2457 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
2458 { ASN_BMPSTRING, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2459 pszDisplayText), CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), TRUE, TRUE,
2460 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
2462 PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
2464 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2465 pvStructInfo, *pcbStructInfo);
2467 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2468 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2469 pcbDecoded, notice ? notice->pNoticeReference : NULL);
2470 TRACE("returning %d\n", ret);
2471 return ret;
2474 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
2475 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2476 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2477 void *pvStructInfo, DWORD *pcbStructInfo)
2479 BOOL ret = FALSE;
2481 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2482 pDecodePara, pvStructInfo, *pcbStructInfo);
2484 __TRY
2486 DWORD bytesNeeded;
2488 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
2489 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2490 NULL);
2491 if (ret)
2493 if (!pvStructInfo)
2494 *pcbStructInfo = bytesNeeded;
2495 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2496 pvStructInfo, pcbStructInfo, bytesNeeded)))
2498 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
2500 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2501 pvStructInfo = *(BYTE **)pvStructInfo;
2502 notice = pvStructInfo;
2503 notice->pNoticeReference =
2504 (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
2505 ((BYTE *)pvStructInfo +
2506 sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
2507 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2508 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
2509 pvStructInfo, &bytesNeeded, NULL);
2513 __EXCEPT_PAGE_FAULT
2515 SetLastError(STATUS_ACCESS_VIOLATION);
2517 __ENDTRY
2518 TRACE("returning %d\n", ret);
2519 return ret;
2522 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2523 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2524 DWORD *pcbDecoded)
2526 BOOL ret;
2527 struct AsnDecodeSequenceItem items[] = {
2528 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2529 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2530 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2531 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2532 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
2533 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2535 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2537 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2538 pvStructInfo, *pcbStructInfo);
2540 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2541 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2542 pcbDecoded, attr ? attr->pszObjId : NULL);
2543 TRACE("returning %d\n", ret);
2544 return ret;
2547 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2548 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2549 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2551 BOOL ret = FALSE;
2553 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2554 pDecodePara, pvStructInfo, *pcbStructInfo);
2556 __TRY
2558 DWORD bytesNeeded;
2560 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2561 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2562 if (ret)
2564 if (!pvStructInfo)
2565 *pcbStructInfo = bytesNeeded;
2566 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2567 pvStructInfo, pcbStructInfo, bytesNeeded)))
2569 PCRYPT_ATTRIBUTE attr;
2571 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2572 pvStructInfo = *(BYTE **)pvStructInfo;
2573 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2574 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2575 sizeof(CRYPT_ATTRIBUTE));
2576 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2577 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2578 NULL);
2582 __EXCEPT_PAGE_FAULT
2584 SetLastError(STATUS_ACCESS_VIOLATION);
2586 __ENDTRY
2587 TRACE("returning %d\n", ret);
2588 return ret;
2591 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2592 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2593 DWORD *pcbDecoded)
2595 struct AsnArrayDescriptor arrayDesc = { 0,
2596 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2597 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2598 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2599 BOOL ret;
2601 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2602 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2603 NULL);
2604 return ret;
2607 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2608 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2609 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2611 BOOL ret = FALSE;
2613 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2614 pDecodePara, pvStructInfo, *pcbStructInfo);
2616 __TRY
2618 DWORD bytesNeeded;
2620 if (!cbEncoded)
2621 SetLastError(CRYPT_E_ASN1_EOD);
2622 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2623 SetLastError(CRYPT_E_ASN1_CORRUPT);
2624 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2625 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2626 NULL)))
2628 if (!pvStructInfo)
2629 *pcbStructInfo = bytesNeeded;
2630 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2631 pvStructInfo, pcbStructInfo, bytesNeeded)))
2633 PCRYPT_ATTRIBUTES attrs;
2635 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2636 pvStructInfo = *(BYTE **)pvStructInfo;
2637 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2638 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2639 sizeof(CRYPT_ATTRIBUTES));
2640 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2641 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2642 &bytesNeeded, NULL);
2646 __EXCEPT_PAGE_FAULT
2648 SetLastError(STATUS_ACCESS_VIOLATION);
2650 __ENDTRY
2651 TRACE("returning %d\n", ret);
2652 return ret;
2655 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2656 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2658 CRYPT_ALGORITHM_IDENTIFIER *algo =
2659 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2660 BOOL ret = TRUE;
2661 struct AsnDecodeSequenceItem items[] = {
2662 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2663 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2664 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2665 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2666 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2667 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2670 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2671 pvStructInfo, *pcbStructInfo, pcbDecoded);
2673 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2674 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2675 pcbDecoded, algo ? algo->pszObjId : NULL);
2676 if (ret && pvStructInfo)
2678 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2679 debugstr_a(algo->pszObjId));
2681 return ret;
2684 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2685 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2686 DWORD *pcbDecoded)
2688 BOOL ret = TRUE;
2689 struct AsnDecodeSequenceItem items[] = {
2690 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2691 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2692 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2693 Algorithm.pszObjId) },
2694 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2695 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2696 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2698 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2700 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2701 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2702 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2703 return ret;
2706 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2707 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2708 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2710 BOOL ret = TRUE;
2712 __TRY
2714 DWORD bytesNeeded;
2716 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2717 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2719 if (!pvStructInfo)
2720 *pcbStructInfo = bytesNeeded;
2721 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2722 pvStructInfo, pcbStructInfo, bytesNeeded)))
2724 PCERT_PUBLIC_KEY_INFO info;
2726 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2727 pvStructInfo = *(BYTE **)pvStructInfo;
2728 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2729 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2730 sizeof(CERT_PUBLIC_KEY_INFO);
2731 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2732 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2733 &bytesNeeded, NULL);
2737 __EXCEPT_PAGE_FAULT
2739 SetLastError(STATUS_ACCESS_VIOLATION);
2740 ret = FALSE;
2742 __ENDTRY
2743 return ret;
2746 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2747 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2749 BOOL ret;
2751 if (cbEncoded < 3)
2753 SetLastError(CRYPT_E_ASN1_CORRUPT);
2754 return FALSE;
2756 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2758 SetLastError(CRYPT_E_ASN1_CORRUPT);
2759 return FALSE;
2761 if (pbEncoded[1] > 1)
2763 SetLastError(CRYPT_E_ASN1_CORRUPT);
2764 return FALSE;
2766 if (pcbDecoded)
2767 *pcbDecoded = 3;
2768 if (!pvStructInfo)
2770 *pcbStructInfo = sizeof(BOOL);
2771 ret = TRUE;
2773 else if (*pcbStructInfo < sizeof(BOOL))
2775 *pcbStructInfo = sizeof(BOOL);
2776 SetLastError(ERROR_MORE_DATA);
2777 ret = FALSE;
2779 else
2781 *pcbStructInfo = sizeof(BOOL);
2782 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2783 ret = TRUE;
2785 TRACE("returning %d (%08x)\n", ret, GetLastError());
2786 return ret;
2789 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2790 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2792 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2793 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2794 BOOL ret;
2796 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2797 pvStructInfo, *pcbStructInfo);
2799 if (cbEncoded < 2)
2801 SetLastError(CRYPT_E_ASN1_CORRUPT);
2802 return FALSE;
2804 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2805 if (1 + lenBytes > cbEncoded)
2807 SetLastError(CRYPT_E_ASN1_CORRUPT);
2808 return FALSE;
2810 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2812 switch (pbEncoded[0] & ASN_TYPE_MASK)
2814 case 1: /* rfc822Name */
2815 case 2: /* dNSName */
2816 case 6: /* uniformResourceIdentifier */
2817 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2818 break;
2819 case 4: /* directoryName */
2820 case 7: /* iPAddress */
2821 bytesNeeded += dataLen;
2822 break;
2823 case 8: /* registeredID */
2824 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2825 &dataLen, NULL);
2826 if (ret)
2828 /* FIXME: ugly, shouldn't need to know internals of OID decode
2829 * function to use it.
2831 bytesNeeded += dataLen - sizeof(LPSTR);
2833 break;
2834 case 0: /* otherName */
2835 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2836 SetLastError(CRYPT_E_ASN1_BADTAG);
2837 ret = FALSE;
2838 break;
2839 case 3: /* x400Address, unimplemented */
2840 case 5: /* ediPartyName, unimplemented */
2841 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2842 SetLastError(CRYPT_E_ASN1_BADTAG);
2843 ret = FALSE;
2844 break;
2845 default:
2846 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2847 SetLastError(CRYPT_E_ASN1_CORRUPT);
2848 ret = FALSE;
2850 if (ret)
2852 if (pcbDecoded)
2853 *pcbDecoded = 1 + lenBytes + dataLen;
2854 if (!entry)
2855 *pcbStructInfo = bytesNeeded;
2856 else if (*pcbStructInfo < bytesNeeded)
2858 *pcbStructInfo = bytesNeeded;
2859 SetLastError(ERROR_MORE_DATA);
2860 ret = FALSE;
2862 else
2864 *pcbStructInfo = bytesNeeded;
2865 /* MS used values one greater than the asn1 ones.. sigh */
2866 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
2867 switch (pbEncoded[0] & ASN_TYPE_MASK)
2869 case 1: /* rfc822Name */
2870 case 2: /* dNSName */
2871 case 6: /* uniformResourceIdentifier */
2873 DWORD i;
2875 for (i = 0; i < dataLen; i++)
2876 entry->u.pwszURL[i] =
2877 (WCHAR)pbEncoded[1 + lenBytes + i];
2878 entry->u.pwszURL[i] = 0;
2879 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2880 debugstr_w(entry->u.pwszURL));
2881 break;
2883 case 4: /* directoryName */
2884 /* The data are memory-equivalent with the IPAddress case,
2885 * fall-through
2887 case 7: /* iPAddress */
2888 /* The next data pointer is in the pwszURL spot, that is,
2889 * the first 4 bytes. Need to move it to the next spot.
2891 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2892 entry->u.IPAddress.cbData = dataLen;
2893 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2894 dataLen);
2895 break;
2896 case 8: /* registeredID */
2897 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2898 &entry->u.pszRegisteredID, &dataLen, NULL);
2899 break;
2904 return ret;
2907 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2908 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2909 DWORD *pcbDecoded)
2911 BOOL ret = TRUE;
2912 struct AsnArrayDescriptor arrayDesc = { 0,
2913 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2914 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2915 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2917 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2918 pvStructInfo, *pcbStructInfo, pcbDecoded);
2920 if (info)
2921 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2922 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2923 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2924 info ? info->rgAltEntry : NULL);
2925 return ret;
2928 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2929 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2930 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2931 DWORD *pcbDecoded)
2933 BOOL ret;
2935 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2936 pvStructInfo, *pcbStructInfo, pcbDecoded);
2938 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2939 * place.
2941 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2942 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2943 pcbDecoded);
2944 if (ret && pvStructInfo)
2946 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2948 if (blob->cbData)
2950 DWORD i;
2951 BYTE temp;
2953 for (i = 0; i < blob->cbData / 2; i++)
2955 temp = blob->pbData[i];
2956 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2957 blob->pbData[blob->cbData - i - 1] = temp;
2961 TRACE("returning %d (%08x)\n", ret, GetLastError());
2962 return ret;
2965 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2966 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2967 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2969 BOOL ret;
2971 __TRY
2973 struct AsnDecodeSequenceItem items[] = {
2974 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2975 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2976 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2977 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2978 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2979 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2980 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2981 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2982 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2983 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2984 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2987 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2988 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2989 pcbStructInfo, NULL, NULL);
2991 __EXCEPT_PAGE_FAULT
2993 SetLastError(STATUS_ACCESS_VIOLATION);
2994 ret = FALSE;
2996 __ENDTRY
2997 return ret;
3000 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
3001 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3002 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3004 BOOL ret;
3006 __TRY
3008 struct AsnDecodeSequenceItem items[] = {
3009 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
3010 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3011 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
3012 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3013 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
3014 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
3015 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3016 AuthorityCertIssuer.rgAltEntry), 0 },
3017 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3018 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3019 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3020 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3021 AuthorityCertSerialNumber.pbData), 0 },
3024 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3025 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3026 pcbStructInfo, NULL, NULL);
3028 __EXCEPT_PAGE_FAULT
3030 SetLastError(STATUS_ACCESS_VIOLATION);
3031 ret = FALSE;
3033 __ENDTRY
3034 return ret;
3037 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
3038 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3039 DWORD *pcbDecoded)
3041 struct AsnDecodeSequenceItem items[] = {
3042 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
3043 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3044 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
3045 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
3046 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
3047 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
3049 CERT_ACCESS_DESCRIPTION *descr = (CERT_ACCESS_DESCRIPTION *)pvStructInfo;
3051 return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3052 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3053 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
3056 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
3057 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3058 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3060 BOOL ret;
3062 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3063 pDecodePara, pvStructInfo, *pcbStructInfo);
3065 __TRY
3067 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3068 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
3069 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
3071 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3072 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3074 __EXCEPT_PAGE_FAULT
3076 SetLastError(STATUS_ACCESS_VIOLATION);
3077 ret = FALSE;
3079 __ENDTRY
3080 return ret;
3083 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
3084 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3086 BOOL ret;
3087 DWORD dataLen;
3089 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3090 pvStructInfo, *pcbStructInfo, pcbDecoded);
3092 /* The caller has already checked the tag, no need to check it again.
3093 * Check the outer length is valid:
3095 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
3097 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3098 DWORD innerLen;
3100 pbEncoded += 1 + lenBytes;
3101 cbEncoded -= 1 + lenBytes;
3102 if (dataLen == CMSG_INDEFINITE_LENGTH)
3103 cbEncoded -= 2; /* space for 0 TLV */
3104 /* Check the inner length is valid: */
3105 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
3107 DWORD decodedLen;
3109 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
3110 pvStructInfo, pcbStructInfo, &decodedLen);
3111 if (dataLen == CMSG_INDEFINITE_LENGTH)
3113 if (*(pbEncoded + decodedLen) != 0 ||
3114 *(pbEncoded + decodedLen + 1) != 0)
3116 TRACE("expected 0 TLV, got {%02x,%02x}\n",
3117 *(pbEncoded + decodedLen),
3118 *(pbEncoded + decodedLen + 1));
3119 SetLastError(CRYPT_E_ASN1_CORRUPT);
3120 ret = FALSE;
3122 else
3123 decodedLen += 2;
3125 if (ret && pcbDecoded)
3127 *pcbDecoded = 1 + lenBytes + decodedLen;
3128 TRACE("decoded %d bytes\n", *pcbDecoded);
3132 return ret;
3135 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
3136 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3137 DWORD *pcbDecoded)
3139 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
3140 struct AsnDecodeSequenceItem items[] = {
3141 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
3142 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3143 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
3144 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
3145 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
3146 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
3147 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
3149 BOOL ret;
3151 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3152 pvStructInfo, *pcbStructInfo, pcbDecoded);
3154 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3155 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3156 pcbDecoded, info ? info->pszObjId : NULL);
3157 return ret;
3160 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
3161 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3162 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3164 BOOL ret = FALSE;
3166 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3167 pDecodePara, pvStructInfo, *pcbStructInfo);
3169 __TRY
3171 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
3172 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3173 if (ret && pvStructInfo)
3175 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3176 pcbStructInfo, *pcbStructInfo);
3177 if (ret)
3179 CRYPT_CONTENT_INFO *info;
3181 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3182 pvStructInfo = *(BYTE **)pvStructInfo;
3183 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
3184 info->pszObjId = (LPSTR)((BYTE *)info +
3185 sizeof(CRYPT_CONTENT_INFO));
3186 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
3187 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3188 pcbStructInfo, NULL);
3192 __EXCEPT_PAGE_FAULT
3194 SetLastError(STATUS_ACCESS_VIOLATION);
3196 __ENDTRY
3197 return ret;
3200 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
3201 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3202 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
3204 BOOL ret;
3205 struct AsnDecodeSequenceItem items[] = {
3206 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
3207 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3208 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
3209 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3210 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
3211 0 },
3212 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
3213 CRYPT_AsnDecodePKCSContentInfoInternal,
3214 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
3215 ContentInfo.pszObjId), 0 },
3216 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
3217 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
3218 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
3221 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3222 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
3223 NULL, NULL);
3224 return ret;
3227 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
3228 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3229 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3231 BOOL ret = TRUE;
3233 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3234 pDecodePara, pvStructInfo, *pcbStructInfo);
3236 __TRY
3238 DWORD bytesNeeded;
3240 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3241 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3243 if (!pvStructInfo)
3244 *pcbStructInfo = bytesNeeded;
3245 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3246 pvStructInfo, pcbStructInfo, bytesNeeded)))
3248 CERT_ALT_NAME_INFO *name;
3250 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3251 pvStructInfo = *(BYTE **)pvStructInfo;
3252 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
3253 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
3254 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
3255 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3256 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3257 &bytesNeeded, NULL);
3261 __EXCEPT_PAGE_FAULT
3263 SetLastError(STATUS_ACCESS_VIOLATION);
3264 ret = FALSE;
3266 __ENDTRY
3267 return ret;
3270 struct PATH_LEN_CONSTRAINT
3272 BOOL fPathLenConstraint;
3273 DWORD dwPathLenConstraint;
3276 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3277 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3278 DWORD *pcbDecoded)
3280 BOOL ret = TRUE;
3281 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3283 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3284 pvStructInfo, *pcbStructInfo, pcbDecoded);
3286 if (!pvStructInfo)
3288 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3289 &size, pcbDecoded);
3290 *pcbStructInfo = bytesNeeded;
3292 else if (*pcbStructInfo < bytesNeeded)
3294 SetLastError(ERROR_MORE_DATA);
3295 *pcbStructInfo = bytesNeeded;
3296 ret = FALSE;
3298 else
3300 struct PATH_LEN_CONSTRAINT *constraint =
3301 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
3303 *pcbStructInfo = bytesNeeded;
3304 size = sizeof(constraint->dwPathLenConstraint);
3305 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3306 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3307 if (ret)
3308 constraint->fPathLenConstraint = TRUE;
3309 TRACE("got an int, dwPathLenConstraint is %d\n",
3310 constraint->dwPathLenConstraint);
3312 TRACE("returning %d (%08x)\n", ret, GetLastError());
3313 return ret;
3316 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3317 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3318 DWORD *pcbDecoded)
3320 BOOL ret;
3321 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3322 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3323 offsetof(CERT_NAME_BLOB, pbData) };
3324 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
3326 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3327 pvStructInfo, *pcbStructInfo, pcbDecoded);
3329 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3330 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3331 entries ? entries->rgItems : NULL);
3332 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3333 return ret;
3336 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3337 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3338 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3340 BOOL ret;
3342 __TRY
3344 struct AsnDecodeSequenceItem items[] = {
3345 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3346 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3347 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3348 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3349 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3350 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3351 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3352 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3353 sizeof(struct GenericArray), TRUE, TRUE,
3354 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3357 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3358 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3359 pcbStructInfo, NULL, NULL);
3361 __EXCEPT_PAGE_FAULT
3363 SetLastError(STATUS_ACCESS_VIOLATION);
3364 ret = FALSE;
3366 __ENDTRY
3367 return ret;
3370 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3371 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3372 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3374 BOOL ret;
3376 __TRY
3378 struct AsnDecodeSequenceItem items[] = {
3379 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3380 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3381 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3382 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3383 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3386 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3387 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3388 pcbStructInfo, NULL, NULL);
3390 __EXCEPT_PAGE_FAULT
3392 SetLastError(STATUS_ACCESS_VIOLATION);
3393 ret = FALSE;
3395 __ENDTRY
3396 return ret;
3399 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
3400 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3401 DWORD *pcbDecoded)
3403 struct AsnDecodeSequenceItem items[] = {
3404 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
3405 pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3406 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
3407 0 },
3408 { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
3409 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3410 offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
3412 BOOL ret;
3413 CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
3415 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3416 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3418 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3419 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3420 pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
3421 return ret;
3424 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
3425 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3426 DWORD *pcbDecoded)
3428 BOOL ret;
3429 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3430 CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
3431 offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
3432 struct GenericArray *entries = pvStructInfo;
3434 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3435 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3437 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3438 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3439 entries ? entries->rgItems : NULL);
3440 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3441 return ret;
3444 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
3445 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3447 struct AsnDecodeSequenceItem items[] = {
3448 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
3449 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3450 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
3451 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3452 CRYPT_AsnDecodePolicyQualifiers, sizeof(struct GenericArray), TRUE,
3453 TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
3455 CERT_POLICY_INFO *info = pvStructInfo;
3456 BOOL ret;
3458 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3459 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3461 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3462 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3463 pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
3464 return ret;
3467 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
3468 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3469 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3471 BOOL ret = FALSE;
3473 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3474 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3476 __TRY
3478 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3479 CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
3480 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
3482 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3483 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3485 __EXCEPT_PAGE_FAULT
3487 SetLastError(STATUS_ACCESS_VIOLATION);
3489 __ENDTRY
3490 return ret;
3493 #define RSA1_MAGIC 0x31415352
3495 struct DECODED_RSA_PUB_KEY
3497 DWORD pubexp;
3498 CRYPT_INTEGER_BLOB modulus;
3501 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3502 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3503 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3505 BOOL ret;
3507 __TRY
3509 struct AsnDecodeSequenceItem items[] = {
3510 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3511 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3512 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3513 0 },
3514 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3515 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3517 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3518 DWORD size = 0;
3520 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3521 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3522 &size, NULL, NULL);
3523 if (ret)
3525 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3526 decodedKey->modulus.cbData;
3528 if (!pvStructInfo)
3530 *pcbStructInfo = bytesNeeded;
3531 ret = TRUE;
3533 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3534 pvStructInfo, pcbStructInfo, bytesNeeded)))
3536 BLOBHEADER *hdr;
3537 RSAPUBKEY *rsaPubKey;
3539 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3540 pvStructInfo = *(BYTE **)pvStructInfo;
3541 hdr = (BLOBHEADER *)pvStructInfo;
3542 hdr->bType = PUBLICKEYBLOB;
3543 hdr->bVersion = CUR_BLOB_VERSION;
3544 hdr->reserved = 0;
3545 hdr->aiKeyAlg = CALG_RSA_KEYX;
3546 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3547 sizeof(BLOBHEADER));
3548 rsaPubKey->magic = RSA1_MAGIC;
3549 rsaPubKey->pubexp = decodedKey->pubexp;
3550 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3551 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3552 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3553 decodedKey->modulus.cbData);
3555 LocalFree(decodedKey);
3558 __EXCEPT_PAGE_FAULT
3560 SetLastError(STATUS_ACCESS_VIOLATION);
3561 ret = FALSE;
3563 __ENDTRY
3564 return ret;
3567 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
3568 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3569 DWORD *pcbDecoded)
3571 BOOL ret;
3572 DWORD bytesNeeded, dataLen;
3574 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3575 pvStructInfo, *pcbStructInfo, pcbDecoded);
3577 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3579 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3581 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3582 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
3583 else
3584 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
3585 if (pcbDecoded)
3586 *pcbDecoded = 1 + lenBytes + dataLen;
3587 if (!pvStructInfo)
3588 *pcbStructInfo = bytesNeeded;
3589 else if (*pcbStructInfo < bytesNeeded)
3591 SetLastError(ERROR_MORE_DATA);
3592 *pcbStructInfo = bytesNeeded;
3593 ret = FALSE;
3595 else
3597 CRYPT_DATA_BLOB *blob;
3599 *pcbStructInfo = bytesNeeded;
3600 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3601 blob->cbData = dataLen;
3602 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3603 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
3604 else
3606 assert(blob->pbData);
3607 if (blob->cbData)
3608 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
3609 blob->cbData);
3613 return ret;
3616 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
3617 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3618 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3620 BOOL ret;
3622 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3623 pDecodePara, pvStructInfo, *pcbStructInfo);
3625 __TRY
3627 DWORD bytesNeeded;
3629 if (!cbEncoded)
3631 SetLastError(CRYPT_E_ASN1_CORRUPT);
3632 ret = FALSE;
3634 else if (pbEncoded[0] != ASN_OCTETSTRING)
3636 SetLastError(CRYPT_E_ASN1_BADTAG);
3637 ret = FALSE;
3639 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3640 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3642 if (!pvStructInfo)
3643 *pcbStructInfo = bytesNeeded;
3644 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3645 pvStructInfo, pcbStructInfo, bytesNeeded)))
3647 CRYPT_DATA_BLOB *blob;
3649 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3650 pvStructInfo = *(BYTE **)pvStructInfo;
3651 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3652 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
3653 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3654 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3655 &bytesNeeded, NULL);
3659 __EXCEPT_PAGE_FAULT
3661 SetLastError(STATUS_ACCESS_VIOLATION);
3662 ret = FALSE;
3664 __ENDTRY
3665 return ret;
3668 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3669 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3671 BOOL ret;
3672 DWORD bytesNeeded, dataLen;
3673 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3675 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3676 pvStructInfo, *pcbStructInfo, pcbDecoded);
3678 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3680 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3681 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3682 else
3683 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3684 if (pcbDecoded)
3685 *pcbDecoded = 1 + lenBytes + dataLen;
3686 if (!pvStructInfo)
3687 *pcbStructInfo = bytesNeeded;
3688 else if (*pcbStructInfo < bytesNeeded)
3690 *pcbStructInfo = bytesNeeded;
3691 SetLastError(ERROR_MORE_DATA);
3692 ret = FALSE;
3694 else
3696 CRYPT_BIT_BLOB *blob;
3698 *pcbStructInfo = bytesNeeded;
3699 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3700 blob->cbData = dataLen - 1;
3701 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3702 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3704 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3706 else
3708 assert(blob->pbData);
3709 if (blob->cbData)
3711 BYTE mask = 0xff << blob->cUnusedBits;
3713 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3714 blob->cbData);
3715 blob->pbData[blob->cbData - 1] &= mask;
3720 return ret;
3723 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3724 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3725 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3727 BOOL ret;
3729 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3730 pDecodePara, pvStructInfo, pcbStructInfo);
3732 __TRY
3734 DWORD bytesNeeded;
3736 if (!cbEncoded)
3738 SetLastError(CRYPT_E_ASN1_CORRUPT);
3739 ret = FALSE;
3741 else if (pbEncoded[0] != ASN_BITSTRING)
3743 SetLastError(CRYPT_E_ASN1_BADTAG);
3744 ret = FALSE;
3746 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3747 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3749 if (!pvStructInfo)
3750 *pcbStructInfo = bytesNeeded;
3751 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3752 pvStructInfo, pcbStructInfo, bytesNeeded)))
3754 CRYPT_BIT_BLOB *blob;
3756 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3757 pvStructInfo = *(BYTE **)pvStructInfo;
3758 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3759 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3760 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3761 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3762 &bytesNeeded, NULL);
3766 __EXCEPT_PAGE_FAULT
3768 SetLastError(STATUS_ACCESS_VIOLATION);
3769 ret = FALSE;
3771 __ENDTRY
3772 TRACE("returning %d (%08x)\n", ret, GetLastError());
3773 return ret;
3776 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
3777 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3778 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3780 BOOL ret;
3781 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3782 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3783 DWORD size = sizeof(buf);
3785 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3786 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, buf,
3787 &size, pcbDecoded);
3788 if (ret)
3790 if (!pvStructInfo)
3791 *pcbStructInfo = sizeof(int);
3792 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3794 int val, i;
3796 if (blob->pbData[blob->cbData - 1] & 0x80)
3798 /* initialize to a negative value to sign-extend */
3799 val = -1;
3801 else
3802 val = 0;
3803 for (i = 0; i < blob->cbData; i++)
3805 val <<= 8;
3806 val |= blob->pbData[blob->cbData - i - 1];
3808 memcpy(pvStructInfo, &val, sizeof(int));
3811 else if (GetLastError() == ERROR_MORE_DATA)
3812 SetLastError(CRYPT_E_ASN1_LARGE);
3813 return ret;
3816 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3817 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3818 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3820 BOOL ret;
3822 __TRY
3824 DWORD bytesNeeded;
3826 if (!cbEncoded)
3828 SetLastError(CRYPT_E_ASN1_EOD);
3829 ret = FALSE;
3831 else if (pbEncoded[0] != ASN_INTEGER)
3833 SetLastError(CRYPT_E_ASN1_BADTAG);
3834 ret = FALSE;
3836 else
3837 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3838 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3839 if (ret)
3841 if (!pvStructInfo)
3842 *pcbStructInfo = bytesNeeded;
3843 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3844 pvStructInfo, pcbStructInfo, bytesNeeded)))
3846 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3847 pvStructInfo = *(BYTE **)pvStructInfo;
3848 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3849 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3850 &bytesNeeded, NULL);
3854 __EXCEPT_PAGE_FAULT
3856 SetLastError(STATUS_ACCESS_VIOLATION);
3857 ret = FALSE;
3859 __ENDTRY
3860 return ret;
3863 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3864 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3865 DWORD *pcbDecoded)
3867 BOOL ret;
3868 DWORD bytesNeeded, dataLen;
3870 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3872 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3874 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3875 if (pcbDecoded)
3876 *pcbDecoded = 1 + lenBytes + dataLen;
3877 if (!pvStructInfo)
3878 *pcbStructInfo = bytesNeeded;
3879 else if (*pcbStructInfo < bytesNeeded)
3881 *pcbStructInfo = bytesNeeded;
3882 SetLastError(ERROR_MORE_DATA);
3883 ret = FALSE;
3885 else
3887 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3889 *pcbStructInfo = bytesNeeded;
3890 blob->cbData = dataLen;
3891 assert(blob->pbData);
3892 if (blob->cbData)
3894 DWORD i;
3896 for (i = 0; i < blob->cbData; i++)
3898 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3899 dataLen - i - 1);
3904 return ret;
3907 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3908 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3909 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3911 BOOL ret;
3913 __TRY
3915 DWORD bytesNeeded;
3917 if (pbEncoded[0] != ASN_INTEGER)
3919 SetLastError(CRYPT_E_ASN1_BADTAG);
3920 ret = FALSE;
3922 else
3923 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3924 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3925 if (ret)
3927 if (!pvStructInfo)
3928 *pcbStructInfo = bytesNeeded;
3929 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3930 pvStructInfo, pcbStructInfo, bytesNeeded)))
3932 CRYPT_INTEGER_BLOB *blob;
3934 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3935 pvStructInfo = *(BYTE **)pvStructInfo;
3936 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3937 blob->pbData = (BYTE *)pvStructInfo +
3938 sizeof(CRYPT_INTEGER_BLOB);
3939 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3940 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3941 &bytesNeeded, NULL);
3945 __EXCEPT_PAGE_FAULT
3947 SetLastError(STATUS_ACCESS_VIOLATION);
3948 ret = FALSE;
3950 __ENDTRY
3951 return ret;
3954 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3955 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3956 DWORD *pcbDecoded)
3958 BOOL ret;
3960 if (pbEncoded[0] == ASN_INTEGER)
3962 DWORD bytesNeeded, dataLen;
3964 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3966 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3968 if (pcbDecoded)
3969 *pcbDecoded = 1 + lenBytes + dataLen;
3970 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3971 if (!pvStructInfo)
3972 *pcbStructInfo = bytesNeeded;
3973 else if (*pcbStructInfo < bytesNeeded)
3975 *pcbStructInfo = bytesNeeded;
3976 SetLastError(ERROR_MORE_DATA);
3977 ret = FALSE;
3979 else
3981 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3983 *pcbStructInfo = bytesNeeded;
3984 blob->cbData = dataLen;
3985 assert(blob->pbData);
3986 /* remove leading zero byte if it exists */
3987 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3989 blob->cbData--;
3990 blob->pbData++;
3992 if (blob->cbData)
3994 DWORD i;
3996 for (i = 0; i < blob->cbData; i++)
3998 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3999 dataLen - i - 1);
4005 else
4007 SetLastError(CRYPT_E_ASN1_BADTAG);
4008 ret = FALSE;
4010 return ret;
4013 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4014 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4015 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4017 BOOL ret;
4019 __TRY
4021 DWORD bytesNeeded;
4023 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4024 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4026 if (!pvStructInfo)
4027 *pcbStructInfo = bytesNeeded;
4028 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4029 pvStructInfo, pcbStructInfo, bytesNeeded)))
4031 CRYPT_INTEGER_BLOB *blob;
4033 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4034 pvStructInfo = *(BYTE **)pvStructInfo;
4035 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
4036 blob->pbData = (BYTE *)pvStructInfo +
4037 sizeof(CRYPT_INTEGER_BLOB);
4038 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4039 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4040 &bytesNeeded, NULL);
4044 __EXCEPT_PAGE_FAULT
4046 SetLastError(STATUS_ACCESS_VIOLATION);
4047 ret = FALSE;
4049 __ENDTRY
4050 return ret;
4053 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4054 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4055 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4057 BOOL ret;
4059 if (!pvStructInfo)
4061 *pcbStructInfo = sizeof(int);
4062 return TRUE;
4064 __TRY
4066 if (pbEncoded[0] == ASN_ENUMERATED)
4068 unsigned int val = 0, i;
4070 if (cbEncoded <= 1)
4072 SetLastError(CRYPT_E_ASN1_EOD);
4073 ret = FALSE;
4075 else if (pbEncoded[1] == 0)
4077 SetLastError(CRYPT_E_ASN1_CORRUPT);
4078 ret = FALSE;
4080 else
4082 /* A little strange looking, but we have to accept a sign byte:
4083 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4084 * assuming a small length is okay here, it has to be in short
4085 * form.
4087 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4089 SetLastError(CRYPT_E_ASN1_LARGE);
4090 return FALSE;
4092 for (i = 0; i < pbEncoded[1]; i++)
4094 val <<= 8;
4095 val |= pbEncoded[2 + i];
4097 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4098 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4100 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4101 pvStructInfo = *(BYTE **)pvStructInfo;
4102 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4106 else
4108 SetLastError(CRYPT_E_ASN1_BADTAG);
4109 ret = FALSE;
4112 __EXCEPT_PAGE_FAULT
4114 SetLastError(STATUS_ACCESS_VIOLATION);
4115 ret = FALSE;
4117 __ENDTRY
4118 return ret;
4121 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4122 * if it fails.
4124 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4125 do { \
4126 BYTE i; \
4128 (word) = 0; \
4129 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4131 if (!isdigit(*(pbEncoded))) \
4133 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4134 ret = FALSE; \
4136 else \
4138 (word) *= 10; \
4139 (word) += *(pbEncoded)++ - '0'; \
4142 } while (0)
4144 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4145 SYSTEMTIME *sysTime)
4147 BOOL ret = TRUE;
4149 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4151 WORD hours, minutes = 0;
4152 BYTE sign = *pbEncoded++;
4154 len--;
4155 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4156 if (ret && hours >= 24)
4158 SetLastError(CRYPT_E_ASN1_CORRUPT);
4159 ret = FALSE;
4161 else if (len >= 2)
4163 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4164 if (ret && minutes >= 60)
4166 SetLastError(CRYPT_E_ASN1_CORRUPT);
4167 ret = FALSE;
4170 if (ret)
4172 if (sign == '+')
4174 sysTime->wHour += hours;
4175 sysTime->wMinute += minutes;
4177 else
4179 if (hours > sysTime->wHour)
4181 sysTime->wDay--;
4182 sysTime->wHour = 24 - (hours - sysTime->wHour);
4184 else
4185 sysTime->wHour -= hours;
4186 if (minutes > sysTime->wMinute)
4188 sysTime->wHour--;
4189 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4191 else
4192 sysTime->wMinute -= minutes;
4196 return ret;
4199 #define MIN_ENCODED_TIME_LENGTH 10
4201 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4202 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4203 DWORD *pcbDecoded)
4205 BOOL ret = FALSE;
4207 if (pbEncoded[0] == ASN_UTCTIME)
4209 if (cbEncoded <= 1)
4210 SetLastError(CRYPT_E_ASN1_EOD);
4211 else if (pbEncoded[1] > 0x7f)
4213 /* long-form date strings really can't be valid */
4214 SetLastError(CRYPT_E_ASN1_CORRUPT);
4216 else
4218 SYSTEMTIME sysTime = { 0 };
4219 BYTE len = pbEncoded[1];
4221 if (len < MIN_ENCODED_TIME_LENGTH)
4222 SetLastError(CRYPT_E_ASN1_CORRUPT);
4223 else
4225 ret = TRUE;
4226 if (pcbDecoded)
4227 *pcbDecoded = 2 + len;
4228 pbEncoded += 2;
4229 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4230 if (sysTime.wYear >= 50)
4231 sysTime.wYear += 1900;
4232 else
4233 sysTime.wYear += 2000;
4234 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4235 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4236 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4237 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4238 if (ret && len > 0)
4240 if (len >= 2 && isdigit(*pbEncoded) &&
4241 isdigit(*(pbEncoded + 1)))
4242 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4243 sysTime.wSecond);
4244 else if (isdigit(*pbEncoded))
4245 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4246 sysTime.wSecond);
4247 if (ret)
4248 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4249 &sysTime);
4251 if (ret)
4253 if (!pvStructInfo)
4254 *pcbStructInfo = sizeof(FILETIME);
4255 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4256 sizeof(FILETIME))))
4257 ret = SystemTimeToFileTime(&sysTime,
4258 (FILETIME *)pvStructInfo);
4263 else
4264 SetLastError(CRYPT_E_ASN1_BADTAG);
4265 return ret;
4268 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4269 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4270 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4272 BOOL ret = FALSE;
4274 __TRY
4276 DWORD bytesNeeded;
4278 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4279 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4280 if (ret)
4282 if (!pvStructInfo)
4283 *pcbStructInfo = bytesNeeded;
4284 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4285 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4287 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4288 pvStructInfo = *(BYTE **)pvStructInfo;
4289 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4290 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4291 &bytesNeeded, NULL);
4295 __EXCEPT_PAGE_FAULT
4297 SetLastError(STATUS_ACCESS_VIOLATION);
4299 __ENDTRY
4300 return ret;
4303 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
4304 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4305 DWORD *pcbDecoded)
4307 BOOL ret = FALSE;
4309 if (pbEncoded[0] == ASN_GENERALTIME)
4311 if (cbEncoded <= 1)
4312 SetLastError(CRYPT_E_ASN1_EOD);
4313 else if (pbEncoded[1] > 0x7f)
4315 /* long-form date strings really can't be valid */
4316 SetLastError(CRYPT_E_ASN1_CORRUPT);
4318 else
4320 BYTE len = pbEncoded[1];
4322 if (len < MIN_ENCODED_TIME_LENGTH)
4323 SetLastError(CRYPT_E_ASN1_CORRUPT);
4324 else
4326 SYSTEMTIME sysTime = { 0 };
4328 ret = TRUE;
4329 if (pcbDecoded)
4330 *pcbDecoded = 2 + len;
4331 pbEncoded += 2;
4332 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
4333 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4334 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4335 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4336 if (ret && len > 0)
4338 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4339 sysTime.wMinute);
4340 if (ret && len > 0)
4341 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4342 sysTime.wSecond);
4343 if (ret && len > 0 && (*pbEncoded == '.' ||
4344 *pbEncoded == ','))
4346 BYTE digits;
4348 pbEncoded++;
4349 len--;
4350 /* workaround macro weirdness */
4351 digits = min(len, 3);
4352 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
4353 sysTime.wMilliseconds);
4355 if (ret)
4356 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4357 &sysTime);
4359 if (ret)
4361 if (!pvStructInfo)
4362 *pcbStructInfo = sizeof(FILETIME);
4363 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4364 sizeof(FILETIME))))
4365 ret = SystemTimeToFileTime(&sysTime,
4366 (FILETIME *)pvStructInfo);
4371 else
4372 SetLastError(CRYPT_E_ASN1_BADTAG);
4373 return ret;
4376 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4377 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4378 DWORD *pcbDecoded)
4380 BOOL ret;
4381 InternalDecodeFunc decode = NULL;
4383 if (pbEncoded[0] == ASN_UTCTIME)
4384 decode = CRYPT_AsnDecodeUtcTimeInternal;
4385 else if (pbEncoded[0] == ASN_GENERALTIME)
4386 decode = CRYPT_AsnDecodeGeneralizedTime;
4387 if (decode)
4388 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
4389 pcbStructInfo, pcbDecoded);
4390 else
4392 SetLastError(CRYPT_E_ASN1_BADTAG);
4393 ret = FALSE;
4395 return ret;
4398 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
4399 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4400 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4402 BOOL ret;
4404 __TRY
4406 DWORD bytesNeeded;
4408 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4409 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4410 if (ret)
4412 if (!pvStructInfo)
4413 *pcbStructInfo = bytesNeeded;
4414 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4415 pvStructInfo, pcbStructInfo, bytesNeeded)))
4417 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4418 pvStructInfo = *(BYTE **)pvStructInfo;
4419 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4420 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4421 &bytesNeeded, NULL);
4425 __EXCEPT_PAGE_FAULT
4427 SetLastError(STATUS_ACCESS_VIOLATION);
4428 ret = FALSE;
4430 __ENDTRY
4431 return ret;
4434 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
4435 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4436 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4438 BOOL ret = TRUE;
4440 __TRY
4442 if (pbEncoded[0] == ASN_SEQUENCEOF)
4444 DWORD bytesNeeded, dataLen, remainingLen, cValue;
4446 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4448 BYTE lenBytes;
4449 const BYTE *ptr;
4451 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4452 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
4453 cValue = 0;
4454 ptr = pbEncoded + 1 + lenBytes;
4455 remainingLen = dataLen;
4456 while (ret && remainingLen)
4458 DWORD nextLen;
4460 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4461 if (ret)
4463 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4465 remainingLen -= 1 + nextLenBytes + nextLen;
4466 ptr += 1 + nextLenBytes + nextLen;
4467 bytesNeeded += sizeof(CRYPT_DER_BLOB);
4468 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
4469 bytesNeeded += 1 + nextLenBytes + nextLen;
4470 cValue++;
4473 if (ret)
4475 CRYPT_SEQUENCE_OF_ANY *seq;
4476 BYTE *nextPtr;
4477 DWORD i;
4479 if (!pvStructInfo)
4480 *pcbStructInfo = bytesNeeded;
4481 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4482 pvStructInfo, pcbStructInfo, bytesNeeded)))
4484 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4485 pvStructInfo = *(BYTE **)pvStructInfo;
4486 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
4487 seq->cValue = cValue;
4488 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
4489 sizeof(*seq));
4490 nextPtr = (BYTE *)seq->rgValue +
4491 cValue * sizeof(CRYPT_DER_BLOB);
4492 ptr = pbEncoded + 1 + lenBytes;
4493 remainingLen = dataLen;
4494 i = 0;
4495 while (ret && remainingLen)
4497 DWORD nextLen;
4499 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4500 if (ret)
4502 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4504 seq->rgValue[i].cbData = 1 + nextLenBytes +
4505 nextLen;
4506 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4507 seq->rgValue[i].pbData = (BYTE *)ptr;
4508 else
4510 seq->rgValue[i].pbData = nextPtr;
4511 memcpy(nextPtr, ptr, 1 + nextLenBytes +
4512 nextLen);
4513 nextPtr += 1 + nextLenBytes + nextLen;
4515 remainingLen -= 1 + nextLenBytes + nextLen;
4516 ptr += 1 + nextLenBytes + nextLen;
4517 i++;
4524 else
4526 SetLastError(CRYPT_E_ASN1_BADTAG);
4527 ret = FALSE;
4530 __EXCEPT_PAGE_FAULT
4532 SetLastError(STATUS_ACCESS_VIOLATION);
4533 ret = FALSE;
4535 __ENDTRY
4536 return ret;
4539 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4540 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4541 DWORD *pcbDecoded)
4543 BOOL ret;
4545 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
4547 DWORD bytesNeeded, dataLen;
4549 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4551 struct AsnArrayDescriptor arrayDesc = {
4552 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
4553 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
4554 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
4555 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4556 DWORD nameLen;
4558 if (dataLen)
4560 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4561 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4562 0, NULL, NULL, &nameLen, NULL, NULL);
4563 /* The CERT_ALT_NAME_INFO's size is included by CRYPT_AsnDecodeArray
4564 * as the sizeof(struct GenericArray), so don't include it in the
4565 * total bytes needed.
4567 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
4568 sizeof(CERT_ALT_NAME_INFO);
4570 else
4571 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
4572 if (pcbDecoded)
4573 *pcbDecoded = 1 + lenBytes + dataLen;
4574 if (!pvStructInfo)
4575 *pcbStructInfo = bytesNeeded;
4576 else if (*pcbStructInfo < bytesNeeded)
4578 *pcbStructInfo = bytesNeeded;
4579 SetLastError(ERROR_MORE_DATA);
4580 ret = FALSE;
4582 else
4584 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
4586 *pcbStructInfo = bytesNeeded;
4587 if (dataLen)
4589 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
4590 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4591 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4592 0, NULL, &name->u.FullName, &nameLen, NULL,
4593 name->u.FullName.rgAltEntry);
4595 else
4596 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
4600 else
4602 SetLastError(CRYPT_E_ASN1_BADTAG);
4603 ret = FALSE;
4605 return ret;
4608 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
4609 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4611 struct AsnDecodeSequenceItem items[] = {
4612 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
4613 DistPointName), CRYPT_AsnDecodeDistPointName,
4614 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
4615 DistPointName.u.FullName.rgAltEntry), 0 },
4616 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
4617 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
4618 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
4619 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
4620 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
4621 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
4623 CRL_DIST_POINT *point = (CRL_DIST_POINT *)pvStructInfo;
4624 BOOL ret;
4626 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4627 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4628 pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
4629 return ret;
4632 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
4633 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4634 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4636 BOOL ret;
4638 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4639 pDecodePara, pvStructInfo, *pcbStructInfo);
4641 __TRY
4643 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4644 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
4645 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
4647 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4648 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4650 __EXCEPT_PAGE_FAULT
4652 SetLastError(STATUS_ACCESS_VIOLATION);
4653 ret = FALSE;
4655 __ENDTRY
4656 return ret;
4659 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
4660 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4661 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4663 BOOL ret;
4665 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4666 pDecodePara, pvStructInfo, *pcbStructInfo);
4668 __TRY
4670 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4671 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4673 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4674 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4676 __EXCEPT_PAGE_FAULT
4678 SetLastError(STATUS_ACCESS_VIOLATION);
4679 ret = FALSE;
4681 __ENDTRY
4682 return ret;
4685 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4686 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4687 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4689 BOOL ret;
4691 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4692 pDecodePara, pvStructInfo, *pcbStructInfo);
4694 __TRY
4696 struct AsnDecodeSequenceItem items[] = {
4697 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4698 DistPointName), CRYPT_AsnDecodeDistPointName,
4699 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4700 offsetof(CRL_ISSUING_DIST_POINT,
4701 DistPointName.u.FullName.rgAltEntry), 0 },
4702 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4703 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4704 FALSE, 0 },
4705 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4706 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4707 FALSE, 0 },
4708 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4709 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4710 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4711 OnlySomeReasonFlags.pbData), 0 },
4712 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4713 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4716 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4717 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4718 pcbStructInfo, NULL, NULL);
4720 __EXCEPT_PAGE_FAULT
4722 SetLastError(STATUS_ACCESS_VIOLATION);
4723 ret = FALSE;
4725 __ENDTRY
4726 return ret;
4729 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
4730 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4731 DWORD *pcbDecoded)
4733 BOOL ret = FALSE;
4735 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4736 pvStructInfo, *pcbStructInfo, pcbDecoded);
4738 if (!cbEncoded)
4740 SetLastError(CRYPT_E_ASN1_EOD);
4741 return FALSE;
4743 if (pbEncoded[0] != (ASN_CONTEXT | 1))
4745 SetLastError(CRYPT_E_ASN1_BADTAG);
4746 return FALSE;
4748 /* The BOOL is implicit: if the integer is present, then it's TRUE */
4749 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
4750 pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo,
4751 pcbDecoded);
4752 if (ret && pvStructInfo)
4753 *(BOOL *)pvStructInfo = TRUE;
4754 TRACE("returning %d\n", ret);
4755 return ret;
4758 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
4759 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4760 DWORD *pcbDecoded)
4762 BOOL ret;
4763 struct AsnDecodeSequenceItem items[] = {
4764 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
4765 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
4766 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
4767 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
4768 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
4769 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
4770 CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0,
4771 0 },
4773 CERT_GENERAL_SUBTREE *subtree = (CERT_GENERAL_SUBTREE *)pvStructInfo;
4775 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4776 pvStructInfo, *pcbStructInfo, pcbDecoded);
4778 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4779 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4780 pcbDecoded, subtree ? (BYTE *)subtree->Base.u.pwszURL : NULL);
4781 if (pcbDecoded)
4783 TRACE("%d\n", *pcbDecoded);
4784 if (*pcbDecoded < cbEncoded)
4785 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
4786 *(pbEncoded + *pcbDecoded + 1));
4788 TRACE("returning %d\n", ret);
4789 return ret;
4792 static BOOL CRYPT_AsnDecodeSubtreeArray(const BYTE *pbEncoded,
4793 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4794 DWORD *pcbDecoded)
4796 BOOL ret = TRUE;
4797 struct AsnArrayDescriptor arrayDesc = { 0,
4798 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4799 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4800 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4802 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4803 pvStructInfo, *pcbStructInfo, pcbDecoded);
4805 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4806 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4807 array ? array->rgItems : NULL);
4808 return ret;
4812 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
4813 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4814 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4816 BOOL ret = FALSE;
4818 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4819 pDecodePara, pvStructInfo, *pcbStructInfo);
4821 __TRY
4823 struct AsnDecodeSequenceItem items[] = {
4824 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4825 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
4826 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4827 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
4828 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
4829 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4830 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4831 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
4834 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4835 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4836 pcbStructInfo, NULL, NULL);
4838 __EXCEPT_PAGE_FAULT
4840 SetLastError(STATUS_ACCESS_VIOLATION);
4842 __ENDTRY
4843 return ret;
4846 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
4847 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4848 DWORD *pcbDecoded)
4850 BOOL ret;
4851 struct AsnDecodeSequenceItem items[] = {
4852 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4853 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4854 Issuer.pbData) },
4855 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4856 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4857 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4859 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4860 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4862 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4863 pvStructInfo, *pcbStructInfo, pcbDecoded);
4865 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4866 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4867 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4868 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4870 SetLastError(CRYPT_E_ASN1_CORRUPT);
4871 ret = FALSE;
4873 TRACE("returning %d\n", ret);
4874 return ret;
4877 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4878 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4879 DWORD *pcbDecoded)
4881 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4882 struct AsnDecodeSequenceItem items[] = {
4883 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4884 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4885 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4886 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4887 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4888 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4889 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4890 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4891 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4892 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4893 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4894 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4895 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4896 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4897 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4898 HashEncryptionAlgorithm.pszObjId), 0 },
4899 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4900 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4901 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4902 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4903 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4904 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4905 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4907 BOOL ret;
4909 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4910 pvStructInfo, *pcbStructInfo);
4912 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4913 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4914 pcbDecoded, info ? info->Issuer.pbData : NULL);
4915 return ret;
4918 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4919 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4920 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4922 BOOL ret = FALSE;
4924 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4925 pDecodePara, pvStructInfo, *pcbStructInfo);
4927 __TRY
4929 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4930 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4931 if (ret && pvStructInfo)
4933 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4934 pcbStructInfo, *pcbStructInfo);
4935 if (ret)
4937 CMSG_SIGNER_INFO *info;
4939 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4940 pvStructInfo = *(BYTE **)pvStructInfo;
4941 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4942 info->Issuer.pbData = ((BYTE *)info +
4943 sizeof(CMSG_SIGNER_INFO));
4944 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4945 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4946 pcbStructInfo, NULL);
4950 __EXCEPT_PAGE_FAULT
4952 SetLastError(STATUS_ACCESS_VIOLATION);
4954 __ENDTRY
4955 TRACE("returning %d\n", ret);
4956 return ret;
4959 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
4960 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4961 DWORD *pcbDecoded)
4963 CERT_ID *id = (CERT_ID *)pvStructInfo;
4964 BOOL ret = FALSE;
4966 if (*pbEncoded == ASN_SEQUENCEOF)
4968 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
4969 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
4970 if (ret)
4972 if (id)
4973 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
4974 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
4975 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4976 sizeof(CERT_ISSUER_SERIAL_NUMBER);
4977 else
4978 *pcbStructInfo = sizeof(CERT_ID);
4981 else if (*pbEncoded == (ASN_CONTEXT | 0))
4983 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
4984 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
4985 if (ret)
4987 if (id)
4988 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
4989 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
4990 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4991 sizeof(CRYPT_DATA_BLOB);
4992 else
4993 *pcbStructInfo = sizeof(CERT_ID);
4996 else
4997 SetLastError(CRYPT_E_ASN1_BADTAG);
4998 return ret;
5001 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5002 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5003 DWORD *pcbDecoded)
5005 CMSG_CMS_SIGNER_INFO *info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
5006 struct AsnDecodeSequenceItem items[] = {
5007 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5008 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5009 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5010 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5011 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
5012 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5013 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5014 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5015 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5016 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5017 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5018 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5019 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5020 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5021 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5022 HashEncryptionAlgorithm.pszObjId), 0 },
5023 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5024 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5025 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5026 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5027 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5028 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5029 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5031 BOOL ret;
5033 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5034 pvStructInfo, *pcbStructInfo);
5036 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5037 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5038 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
5039 return ret;
5042 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5043 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5044 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5046 BOOL ret = FALSE;
5048 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5049 pDecodePara, pvStructInfo, *pcbStructInfo);
5051 __TRY
5053 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5054 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5055 if (ret && pvStructInfo)
5057 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5058 pcbStructInfo, *pcbStructInfo);
5059 if (ret)
5061 CMSG_CMS_SIGNER_INFO *info;
5063 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5064 pvStructInfo = *(BYTE **)pvStructInfo;
5065 info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
5066 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
5067 sizeof(CMSG_CMS_SIGNER_INFO));
5068 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5069 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5070 pcbStructInfo, NULL);
5074 __EXCEPT_PAGE_FAULT
5076 SetLastError(STATUS_ACCESS_VIOLATION);
5078 __ENDTRY
5079 TRACE("returning %d\n", ret);
5080 return ret;
5083 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5084 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5086 BOOL ret;
5087 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5088 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5089 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
5090 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
5092 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5093 pvStructInfo, *pcbStructInfo, pcbDecoded);
5095 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
5096 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
5097 array ? array->rgItems : NULL);
5098 return ret;
5101 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5102 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5103 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5105 BOOL ret = FALSE;
5106 struct AsnDecodeSequenceItem items[] = {
5107 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5108 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5109 /* Placeholder for the hash algorithms - redundant with those in the
5110 * signers, so just ignore them.
5112 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5113 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5114 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5115 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5116 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5117 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
5118 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
5119 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5120 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5121 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
5122 sizeof(struct GenericArray), TRUE, TRUE,
5123 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5124 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5125 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
5126 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5129 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5130 pDecodePara, signedInfo, *pcbSignedInfo);
5132 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5133 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5134 NULL, NULL);
5135 TRACE("returning %d\n", ret);
5136 return ret;
5139 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
5140 LPCSTR lpszStructType)
5142 CryptDecodeObjectExFunc decodeFunc = NULL;
5144 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
5145 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
5147 SetLastError(ERROR_FILE_NOT_FOUND);
5148 return NULL;
5150 if (!HIWORD(lpszStructType))
5152 switch (LOWORD(lpszStructType))
5154 case LOWORD(X509_CERT):
5155 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
5156 break;
5157 case LOWORD(X509_CERT_TO_BE_SIGNED):
5158 decodeFunc = CRYPT_AsnDecodeCert;
5159 break;
5160 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
5161 decodeFunc = CRYPT_AsnDecodeCRL;
5162 break;
5163 case LOWORD(X509_EXTENSIONS):
5164 decodeFunc = CRYPT_AsnDecodeExtensions;
5165 break;
5166 case LOWORD(X509_NAME_VALUE):
5167 decodeFunc = CRYPT_AsnDecodeNameValue;
5168 break;
5169 case LOWORD(X509_NAME):
5170 decodeFunc = CRYPT_AsnDecodeName;
5171 break;
5172 case LOWORD(X509_PUBLIC_KEY_INFO):
5173 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
5174 break;
5175 case LOWORD(X509_AUTHORITY_KEY_ID):
5176 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5177 break;
5178 case LOWORD(X509_ALTERNATE_NAME):
5179 decodeFunc = CRYPT_AsnDecodeAltName;
5180 break;
5181 case LOWORD(X509_BASIC_CONSTRAINTS):
5182 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5183 break;
5184 case LOWORD(X509_BASIC_CONSTRAINTS2):
5185 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5186 break;
5187 case LOWORD(X509_CERT_POLICIES):
5188 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5189 break;
5190 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
5191 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
5192 break;
5193 case LOWORD(X509_UNICODE_NAME):
5194 decodeFunc = CRYPT_AsnDecodeUnicodeName;
5195 break;
5196 case LOWORD(PKCS_ATTRIBUTE):
5197 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
5198 break;
5199 case LOWORD(X509_UNICODE_NAME_VALUE):
5200 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
5201 break;
5202 case LOWORD(X509_OCTET_STRING):
5203 decodeFunc = CRYPT_AsnDecodeOctets;
5204 break;
5205 case LOWORD(X509_BITS):
5206 case LOWORD(X509_KEY_USAGE):
5207 decodeFunc = CRYPT_AsnDecodeBits;
5208 break;
5209 case LOWORD(X509_INTEGER):
5210 decodeFunc = CRYPT_AsnDecodeInt;
5211 break;
5212 case LOWORD(X509_MULTI_BYTE_INTEGER):
5213 decodeFunc = CRYPT_AsnDecodeInteger;
5214 break;
5215 case LOWORD(X509_MULTI_BYTE_UINT):
5216 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
5217 break;
5218 case LOWORD(X509_ENUMERATED):
5219 decodeFunc = CRYPT_AsnDecodeEnumerated;
5220 break;
5221 case LOWORD(X509_CHOICE_OF_TIME):
5222 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
5223 break;
5224 case LOWORD(X509_AUTHORITY_KEY_ID2):
5225 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5226 break;
5227 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
5228 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5229 break;
5230 case LOWORD(PKCS_CONTENT_INFO):
5231 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
5232 break;
5233 case LOWORD(X509_SEQUENCE_OF_ANY):
5234 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
5235 break;
5236 case LOWORD(PKCS_UTC_TIME):
5237 decodeFunc = CRYPT_AsnDecodeUtcTime;
5238 break;
5239 case LOWORD(X509_CRL_DIST_POINTS):
5240 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5241 break;
5242 case LOWORD(X509_ENHANCED_KEY_USAGE):
5243 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5244 break;
5245 case LOWORD(PKCS_CTL):
5246 decodeFunc = CRYPT_AsnDecodeCTL;
5247 break;
5248 case LOWORD(PKCS_SMIME_CAPABILITIES):
5249 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5250 break;
5251 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
5252 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5253 break;
5254 case LOWORD(PKCS_ATTRIBUTES):
5255 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
5256 break;
5257 case LOWORD(X509_ISSUING_DIST_POINT):
5258 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5259 break;
5260 case LOWORD(X509_NAME_CONSTRAINTS):
5261 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5262 break;
5263 case LOWORD(PKCS7_SIGNER_INFO):
5264 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
5265 break;
5266 case LOWORD(CMS_SIGNER_INFO):
5267 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
5268 break;
5271 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
5272 decodeFunc = CRYPT_AsnDecodeExtensions;
5273 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
5274 decodeFunc = CRYPT_AsnDecodeUtcTime;
5275 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
5276 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5277 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
5278 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5279 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
5280 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5281 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
5282 decodeFunc = CRYPT_AsnDecodeEnumerated;
5283 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
5284 decodeFunc = CRYPT_AsnDecodeBits;
5285 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
5286 decodeFunc = CRYPT_AsnDecodeOctets;
5287 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
5288 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5289 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
5290 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5291 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
5292 decodeFunc = CRYPT_AsnDecodeAltName;
5293 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
5294 decodeFunc = CRYPT_AsnDecodeAltName;
5295 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
5296 decodeFunc = CRYPT_AsnDecodeAltName;
5297 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
5298 decodeFunc = CRYPT_AsnDecodeAltName;
5299 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
5300 decodeFunc = CRYPT_AsnDecodeAltName;
5301 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
5302 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5303 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
5304 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5305 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
5306 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5307 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
5308 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5309 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
5310 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5311 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
5312 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5313 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
5314 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5315 else if (!strcmp(lpszStructType, szOID_CTL))
5316 decodeFunc = CRYPT_AsnDecodeCTL;
5317 return decodeFunc;
5320 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
5321 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5323 static HCRYPTOIDFUNCSET set = NULL;
5324 CryptDecodeObjectFunc decodeFunc = NULL;
5326 if (!set)
5327 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
5328 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5329 (void **)&decodeFunc, hFunc);
5330 return decodeFunc;
5333 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
5334 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5336 static HCRYPTOIDFUNCSET set = NULL;
5337 CryptDecodeObjectExFunc decodeFunc = NULL;
5339 if (!set)
5340 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
5341 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5342 (void **)&decodeFunc, hFunc);
5343 return decodeFunc;
5346 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5347 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
5348 DWORD *pcbStructInfo)
5350 BOOL ret = FALSE;
5351 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
5352 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
5353 HCRYPTOIDFUNCADDR hFunc = NULL;
5355 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
5356 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
5357 pvStructInfo, pcbStructInfo);
5359 if (!pvStructInfo && !pcbStructInfo)
5361 SetLastError(ERROR_INVALID_PARAMETER);
5362 return FALSE;
5364 if (cbEncoded > MAX_ENCODED_LEN)
5366 SetLastError(CRYPT_E_ASN1_LARGE);
5367 return FALSE;
5370 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
5371 lpszStructType)))
5373 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5374 debugstr_a(lpszStructType));
5375 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
5376 lpszStructType, &hFunc);
5377 if (!pCryptDecodeObject)
5378 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
5379 lpszStructType, &hFunc);
5381 if (pCryptDecodeObject)
5382 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5383 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5384 else if (pCryptDecodeObjectEx)
5385 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
5386 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
5387 pvStructInfo, pcbStructInfo);
5388 if (hFunc)
5389 CryptFreeOIDFunctionAddress(hFunc, 0);
5390 TRACE_(crypt)("returning %d\n", ret);
5391 return ret;
5394 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5395 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5396 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5398 BOOL ret = FALSE;
5399 CryptDecodeObjectExFunc decodeFunc;
5400 HCRYPTOIDFUNCADDR hFunc = NULL;
5402 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
5403 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5404 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5406 if (!pvStructInfo && !pcbStructInfo)
5408 SetLastError(ERROR_INVALID_PARAMETER);
5409 return FALSE;
5411 if (cbEncoded > MAX_ENCODED_LEN)
5413 SetLastError(CRYPT_E_ASN1_LARGE);
5414 return FALSE;
5417 SetLastError(NOERROR);
5418 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5419 *(BYTE **)pvStructInfo = NULL;
5420 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
5421 if (!decodeFunc)
5423 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5424 debugstr_a(lpszStructType));
5425 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
5426 &hFunc);
5428 if (decodeFunc)
5429 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5430 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5431 else
5433 CryptDecodeObjectFunc pCryptDecodeObject =
5434 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
5436 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
5437 * directly, as that could cause an infinite loop.
5439 if (pCryptDecodeObject)
5441 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5443 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5444 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
5445 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5446 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
5447 ret = pCryptDecodeObject(dwCertEncodingType,
5448 lpszStructType, pbEncoded, cbEncoded, dwFlags,
5449 *(BYTE **)pvStructInfo, pcbStructInfo);
5451 else
5452 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5453 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5456 if (hFunc)
5457 CryptFreeOIDFunctionAddress(hFunc, 0);
5458 TRACE_(crypt)("returning %d\n", ret);
5459 return ret;