widl: Replace write_name() by get_name() to make the code more readable.
[wine.git] / dlls / crypt32 / decode.c
blobeb782d3e0180925c6579212eb47c2d85b1167c68
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 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
100 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
101 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
102 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
103 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
104 * member has been initialized, doesn't do exception handling, and doesn't do
105 * memory allocation. Also doesn't check tag, assumes the caller has checked
106 * it.
108 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
109 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
110 DWORD *pcbDecoded);
111 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
112 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
113 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
114 DWORD *pcbDecoded);
115 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
116 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
117 DWORD *pcbDecoded);
119 /* Gets the number of length bytes from the given (leading) length byte */
120 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
122 /* Helper function to get the encoded length of the data starting at pbEncoded,
123 * where pbEncoded[0] is the tag. If the data are too short to contain a
124 * length or if the length is too large for cbEncoded, sets an appropriate
125 * error code and returns FALSE. If the encoded length is unknown due to
126 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
128 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
129 DWORD *len)
131 BOOL ret;
133 if (cbEncoded <= 1)
135 SetLastError(CRYPT_E_ASN1_CORRUPT);
136 ret = FALSE;
138 else if (pbEncoded[1] <= 0x7f)
140 if (pbEncoded[1] + 1 > cbEncoded)
142 SetLastError(CRYPT_E_ASN1_EOD);
143 ret = FALSE;
145 else
147 *len = pbEncoded[1];
148 ret = TRUE;
151 else if (pbEncoded[1] == 0x80)
153 *len = CMSG_INDEFINITE_LENGTH;
154 ret = TRUE;
156 else
158 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
160 if (lenLen > sizeof(DWORD) + 1)
162 SetLastError(CRYPT_E_ASN1_LARGE);
163 ret = FALSE;
165 else if (lenLen + 2 > cbEncoded)
167 SetLastError(CRYPT_E_ASN1_CORRUPT);
168 ret = FALSE;
170 else
172 DWORD out = 0;
174 pbEncoded += 2;
175 while (--lenLen)
177 out <<= 8;
178 out |= *pbEncoded++;
180 if (out + lenLen + 1 > cbEncoded)
182 SetLastError(CRYPT_E_ASN1_EOD);
183 ret = FALSE;
185 else
187 *len = out;
188 ret = TRUE;
192 return ret;
195 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
196 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
198 BOOL ret;
200 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
201 *len == CMSG_INDEFINITE_LENGTH)
203 SetLastError(CRYPT_E_ASN1_CORRUPT);
204 ret = FALSE;
206 return ret;
209 /* Helper function to check *pcbStructInfo, set it to the required size, and
210 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
211 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
212 * pointer to the newly allocated memory.
214 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
215 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
216 DWORD bytesNeeded)
218 BOOL ret = TRUE;
220 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
222 if (pDecodePara && pDecodePara->pfnAlloc)
223 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
224 else
225 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
226 if (!*(BYTE **)pvStructInfo)
227 ret = FALSE;
228 else
229 *pcbStructInfo = bytesNeeded;
231 else if (*pcbStructInfo < bytesNeeded)
233 *pcbStructInfo = bytesNeeded;
234 SetLastError(ERROR_MORE_DATA);
235 ret = FALSE;
237 else
238 *pcbStructInfo = bytesNeeded;
239 return ret;
242 static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
244 if (pDecodePara && pDecodePara->pfnFree)
245 pDecodePara->pfnFree(pv);
246 else
247 LocalFree(pv);
250 /* Helper function to check *pcbStructInfo and set it to the required size.
251 * Assumes pvStructInfo is not NULL.
253 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
255 BOOL ret;
257 if (*pcbStructInfo < bytesNeeded)
259 *pcbStructInfo = bytesNeeded;
260 SetLastError(ERROR_MORE_DATA);
261 ret = FALSE;
263 else
265 *pcbStructInfo = bytesNeeded;
266 ret = TRUE;
268 return ret;
271 /* tag:
272 * The expected tag of the item. If tag is 0, decodeFunc is called
273 * regardless of the tag value seen.
274 * offset:
275 * A sequence is decoded into a struct. The offset member is the
276 * offset of this item within that struct.
277 * decodeFunc:
278 * The decoder function to use. If this is NULL, then the member isn't
279 * decoded, but minSize space is reserved for it.
280 * minSize:
281 * The minimum amount of space occupied after decoding. You must set this.
282 * optional:
283 * If true, and the tag doesn't match the expected tag for this item,
284 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
285 * filled with 0 for this member.
286 * hasPointer, pointerOffset:
287 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
288 * the offset within the struct of the data pointer (or to the
289 * first data pointer, if more than one exist).
290 * size:
291 * Used by CRYPT_AsnDecodeSequence, not for your use.
293 struct AsnDecodeSequenceItem
295 BYTE tag;
296 DWORD offset;
297 InternalDecodeFunc decodeFunc;
298 DWORD minSize;
299 BOOL optional;
300 BOOL hasPointer;
301 DWORD pointerOffset;
302 DWORD size;
305 /* Decodes the items in a sequence, where the items are described in items,
306 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
307 * pvStructInfo. nextData is a pointer to the memory location at which the
308 * first decoded item with a dynamic pointer should point.
309 * Upon decoding, *cbDecoded is the total number of bytes decoded.
310 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
312 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
313 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
314 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
316 BOOL ret;
317 DWORD i, decoded = 0;
318 const BYTE *ptr = pbEncoded;
320 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
321 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
323 for (i = 0, ret = TRUE; ret && i < cItem; i++)
325 if (cbEncoded - (ptr - pbEncoded) != 0)
327 DWORD itemLen;
329 if ((ret = CRYPT_GetLengthIndefinite(ptr,
330 cbEncoded - (ptr - pbEncoded), &itemLen)))
332 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
334 if (ptr[0] == items[i].tag || !items[i].tag)
336 DWORD itemEncodedLen;
338 if (itemLen == CMSG_INDEFINITE_LENGTH)
339 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
340 else
341 itemEncodedLen = 1 + itemLenBytes + itemLen;
342 if (nextData && pvStructInfo && items[i].hasPointer)
344 TRACE("Setting next pointer to %p\n",
345 nextData);
346 *(BYTE **)((BYTE *)pvStructInfo +
347 items[i].pointerOffset) = nextData;
349 if (items[i].decodeFunc)
351 DWORD itemDecoded;
353 if (pvStructInfo)
354 TRACE("decoding item %d\n", i);
355 else
356 TRACE("sizing item %d\n", i);
357 ret = items[i].decodeFunc(ptr, itemEncodedLen,
358 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
359 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
360 : NULL, &items[i].size, &itemDecoded);
361 if (ret)
363 /* Account for alignment padding */
364 if (items[i].size % sizeof(DWORD_PTR))
365 items[i].size += sizeof(DWORD_PTR) -
366 items[i].size % sizeof(DWORD_PTR);
367 TRACE("item %d size: %d\n", i, items[i].size);
368 if (nextData && items[i].hasPointer &&
369 items[i].size > items[i].minSize)
370 nextData += items[i].size - items[i].minSize;
371 if (itemDecoded > itemEncodedLen)
373 WARN("decoded length %d exceeds encoded %d\n",
374 itemDecoded, itemEncodedLen);
375 SetLastError(CRYPT_E_ASN1_CORRUPT);
376 ret = FALSE;
378 else
380 if (itemLen == CMSG_INDEFINITE_LENGTH)
382 if (itemDecoded > itemEncodedLen - 2 ||
383 *(ptr + itemDecoded) != 0 ||
384 *(ptr + itemDecoded + 1) != 0)
386 TRACE("expected 0 TLV\n");
387 SetLastError(CRYPT_E_ASN1_CORRUPT);
388 ret = FALSE;
390 else
391 itemDecoded += 2;
393 if (ret)
395 ptr += itemDecoded;
396 decoded += itemDecoded;
397 TRACE("item %d: decoded %d bytes\n", i,
398 itemDecoded);
402 else if (items[i].optional &&
403 GetLastError() == CRYPT_E_ASN1_BADTAG)
405 TRACE("skipping optional item %d\n", i);
406 items[i].size = items[i].minSize;
407 SetLastError(NOERROR);
408 ret = TRUE;
410 else
411 TRACE("item %d failed: %08x\n", i,
412 GetLastError());
414 else if (itemLen == CMSG_INDEFINITE_LENGTH)
416 ERR("can't use indefinite length encoding without a decoder\n");
417 SetLastError(CRYPT_E_ASN1_CORRUPT);
418 ret = FALSE;
420 else
422 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
423 ptr += itemEncodedLen;
424 decoded += itemEncodedLen;
425 items[i].size = items[i].minSize;
428 else if (items[i].optional)
430 TRACE("skipping optional item %d\n", i);
431 items[i].size = items[i].minSize;
433 else
435 TRACE("item %d: tag %02x doesn't match expected %02x\n",
436 i, ptr[0], items[i].tag);
437 SetLastError(CRYPT_E_ASN1_BADTAG);
438 ret = FALSE;
442 else if (items[i].optional)
444 TRACE("missing optional item %d, skipping\n", i);
445 items[i].size = items[i].minSize;
447 else
449 TRACE("not enough bytes for item %d, failing\n", i);
450 SetLastError(CRYPT_E_ASN1_CORRUPT);
451 ret = FALSE;
454 if (cbDecoded)
455 *cbDecoded = decoded;
456 TRACE("returning %d\n", ret);
457 return ret;
460 /* This decodes an arbitrary sequence into a contiguous block of memory
461 * (basically, a struct.) Each element being decoded is described by a struct
462 * AsnDecodeSequenceItem, see above.
463 * startingPointer is an optional pointer to the first place where dynamic
464 * data will be stored. If you know the starting offset, you may pass it
465 * here. Otherwise, pass NULL, and one will be inferred from the items.
467 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
468 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
469 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
470 DWORD *pcbDecoded, void *startingPointer)
472 BOOL ret;
474 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
475 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
476 startingPointer);
478 if (pbEncoded[0] == ASN_SEQUENCE)
480 DWORD dataLen;
482 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
484 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
485 const BYTE *ptr = pbEncoded + 1 + lenBytes;
486 BOOL indefinite = FALSE;
488 cbEncoded -= 1 + lenBytes;
489 if (dataLen == CMSG_INDEFINITE_LENGTH)
491 dataLen = cbEncoded;
492 indefinite = TRUE;
494 else if (cbEncoded < dataLen)
496 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
497 cbEncoded);
498 SetLastError(CRYPT_E_ASN1_CORRUPT);
499 ret = FALSE;
501 if (ret)
503 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
504 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
505 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
507 if (cbDecoded > cbEncoded - 2)
509 /* Not enough space for 0 TLV */
510 SetLastError(CRYPT_E_ASN1_CORRUPT);
511 ret = FALSE;
513 else if (*(ptr + cbDecoded) != 0 ||
514 *(ptr + cbDecoded + 1) != 0)
516 TRACE("expected 0 TLV\n");
517 SetLastError(CRYPT_E_ASN1_CORRUPT);
518 ret = FALSE;
520 else
521 cbDecoded += 2;
524 if (ret && !indefinite && cbDecoded != dataLen)
526 TRACE("expected %d decoded, got %d, failing\n", dataLen,
527 cbDecoded);
528 SetLastError(CRYPT_E_ASN1_CORRUPT);
529 ret = FALSE;
531 if (ret)
533 DWORD i, bytesNeeded = 0, structSize = 0;
535 for (i = 0; i < cItem; i++)
537 bytesNeeded += items[i].size;
538 structSize += items[i].minSize;
540 if (pcbDecoded)
541 *pcbDecoded = 1 + lenBytes + cbDecoded;
542 if (!pvStructInfo)
543 *pcbStructInfo = bytesNeeded;
544 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
545 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
547 BYTE *nextData;
549 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
550 pvStructInfo = *(BYTE **)pvStructInfo;
551 if (startingPointer)
552 nextData = (BYTE *)startingPointer;
553 else
554 nextData = (BYTE *)pvStructInfo + structSize;
555 memset(pvStructInfo, 0, structSize);
556 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
557 ptr, dataLen, dwFlags, pvStructInfo, nextData,
558 &cbDecoded);
559 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
560 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
565 else
567 SetLastError(CRYPT_E_ASN1_BADTAG);
568 ret = FALSE;
570 TRACE("returning %d (%08x)\n", ret, GetLastError());
571 return ret;
574 /* tag:
575 * The expected tag of the entire encoded array (usually a variant
576 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
577 * regardless of the tag seen.
578 * decodeFunc:
579 * used to decode each item in the array
580 * itemSize:
581 * is the minimum size of each decoded item
582 * hasPointer:
583 * indicates whether each item has a dynamic pointer
584 * pointerOffset:
585 * indicates the offset within itemSize at which the pointer exists
587 struct AsnArrayDescriptor
589 BYTE tag;
590 InternalDecodeFunc decodeFunc;
591 DWORD itemSize;
592 BOOL hasPointer;
593 DWORD pointerOffset;
596 struct AsnArrayItemSize
598 DWORD encodedLen;
599 DWORD size;
602 /* Decodes an array of like types into a struct GenericArray.
603 * The layout and decoding of the array are described by a struct
604 * AsnArrayDescriptor.
606 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
607 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
608 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
609 DWORD *pcbDecoded, void *startingPointer)
611 BOOL ret = TRUE;
613 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
614 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
615 startingPointer);
617 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
619 DWORD dataLen;
621 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
623 DWORD bytesNeeded, cItems = 0, decoded;
624 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
625 /* There can be arbitrarily many items, but there is often only one.
627 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
629 decoded = 1 + lenBytes;
630 bytesNeeded = sizeof(struct GenericArray);
631 if (dataLen)
633 const BYTE *ptr;
634 BOOL doneDecoding = FALSE;
636 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
638 if (dataLen == CMSG_INDEFINITE_LENGTH)
640 if (ptr[0] == 0)
642 doneDecoding = TRUE;
643 if (ptr[1] != 0)
645 SetLastError(CRYPT_E_ASN1_CORRUPT);
646 ret = FALSE;
648 else
649 decoded += 2;
652 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
653 doneDecoding = TRUE;
654 if (!doneDecoding)
656 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
658 /* Each item decoded may not tolerate extraneous bytes,
659 * so get the length of the next element if known.
661 if ((ret = CRYPT_GetLengthIndefinite(ptr,
662 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
664 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
665 itemEncoded = cbEncoded - (ptr - pbEncoded);
666 else
667 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
668 itemDataLen;
670 if (ret)
671 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
672 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
673 &itemDecoded);
674 if (ret)
676 cItems++;
677 if (itemSizes != &itemSize)
678 itemSizes = CryptMemRealloc(itemSizes,
679 cItems * sizeof(struct AsnArrayItemSize));
680 else if (cItems > 1)
682 itemSizes =
683 CryptMemAlloc(
684 cItems * sizeof(struct AsnArrayItemSize));
685 if (itemSizes)
686 memcpy(itemSizes, &itemSize,
687 sizeof(itemSize));
689 if (itemSizes)
691 decoded += itemDecoded;
692 itemSizes[cItems - 1].encodedLen = itemEncoded;
693 itemSizes[cItems - 1].size = size;
694 bytesNeeded += size;
695 ptr += itemEncoded;
697 else
698 ret = FALSE;
703 if (ret)
705 if (pcbDecoded)
706 *pcbDecoded = decoded;
707 if (!pvStructInfo)
708 *pcbStructInfo = bytesNeeded;
709 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
710 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
712 DWORD i;
713 BYTE *nextData;
714 const BYTE *ptr;
715 struct GenericArray *array;
717 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
718 pvStructInfo = *(BYTE **)pvStructInfo;
719 array = (struct GenericArray *)pvStructInfo;
720 array->cItems = cItems;
721 if (startingPointer)
722 array->rgItems = startingPointer;
723 else
724 array->rgItems = (BYTE *)array +
725 sizeof(struct GenericArray);
726 nextData = array->rgItems +
727 array->cItems * arrayDesc->itemSize;
728 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
729 i < cItems && ptr - pbEncoded - 1 - lenBytes <
730 dataLen; i++)
732 DWORD itemDecoded;
734 if (arrayDesc->hasPointer)
735 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
736 + arrayDesc->pointerOffset) = nextData;
737 ret = arrayDesc->decodeFunc(ptr,
738 itemSizes[i].encodedLen,
739 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
740 array->rgItems + i * arrayDesc->itemSize,
741 &itemSizes[i].size, &itemDecoded);
742 if (ret)
744 nextData += itemSizes[i].size - arrayDesc->itemSize;
745 ptr += itemDecoded;
748 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
749 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
752 if (itemSizes != &itemSize)
753 CryptMemFree(itemSizes);
756 else
758 SetLastError(CRYPT_E_ASN1_BADTAG);
759 ret = FALSE;
761 return ret;
764 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
765 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
766 * to CRYPT_E_ASN1_CORRUPT.
767 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
768 * set!
770 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
771 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
773 BOOL ret;
774 DWORD dataLen;
776 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
778 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
779 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
781 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
782 bytesNeeded += 1 + lenBytes + dataLen;
784 if (pcbDecoded)
785 *pcbDecoded = 1 + lenBytes + dataLen;
786 if (!pvStructInfo)
787 *pcbStructInfo = bytesNeeded;
788 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
790 CRYPT_DER_BLOB *blob;
792 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
793 pvStructInfo = *(BYTE **)pvStructInfo;
794 blob = (CRYPT_DER_BLOB *)pvStructInfo;
795 blob->cbData = 1 + lenBytes + dataLen;
796 if (blob->cbData)
798 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
799 blob->pbData = (BYTE *)pbEncoded;
800 else
802 assert(blob->pbData);
803 memcpy(blob->pbData, pbEncoded, blob->cbData);
806 else
808 SetLastError(CRYPT_E_ASN1_CORRUPT);
809 ret = FALSE;
813 return ret;
816 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
817 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
818 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
819 DWORD *pcbDecoded)
821 BOOL ret;
823 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
824 pvStructInfo, *pcbStructInfo, pcbDecoded);
826 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
827 * place.
829 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
830 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
831 pcbDecoded);
832 if (ret && pvStructInfo)
834 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
836 if (blob->cbData)
838 DWORD i;
839 BYTE temp;
841 for (i = 0; i < blob->cbData / 2; i++)
843 temp = blob->pbData[i];
844 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
845 blob->pbData[blob->cbData - i - 1] = temp;
849 TRACE("returning %d (%08x)\n", ret, GetLastError());
850 return ret;
853 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
854 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
855 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
857 BOOL ret = TRUE;
859 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
860 pDecodePara, pvStructInfo, *pcbStructInfo);
862 __TRY
864 struct AsnDecodeSequenceItem items[] = {
865 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
866 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
867 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
868 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
869 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
870 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
871 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
872 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
873 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
874 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
877 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
878 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
879 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
880 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
881 pcbStructInfo, NULL, NULL);
883 __EXCEPT_PAGE_FAULT
885 SetLastError(STATUS_ACCESS_VIOLATION);
886 ret = FALSE;
888 __ENDTRY
890 TRACE("Returning %d (%08x)\n", ret, GetLastError());
891 return ret;
894 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
895 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
897 BOOL ret;
898 DWORD dataLen;
900 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
902 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
904 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
905 dwFlags, pvStructInfo, pcbStructInfo, NULL);
906 if (pcbDecoded)
907 *pcbDecoded = 1 + lenBytes + dataLen;
909 return ret;
912 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
913 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
915 BOOL ret;
917 struct AsnDecodeSequenceItem items[] = {
918 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
919 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
920 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
921 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
924 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
925 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
926 pcbDecoded, NULL);
927 return ret;
930 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
931 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
932 DWORD *pcbDecoded)
934 BOOL ret;
935 DWORD dataLen;
937 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
939 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
941 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
942 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
943 if (ret && pcbDecoded)
944 *pcbDecoded = 1 + lenBytes + dataLen;
946 return ret;
949 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
950 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
951 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
953 BOOL ret = TRUE;
954 struct AsnDecodeSequenceItem items[] = {
955 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
956 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
957 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
958 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
959 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
960 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
961 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
962 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
963 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
964 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
965 Issuer.pbData) },
966 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
967 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
968 FALSE, 0 },
969 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
970 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
971 Subject.pbData) },
972 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
973 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
974 FALSE, TRUE, offsetof(CERT_INFO,
975 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
976 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
977 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
978 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
979 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
980 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
981 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
982 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
983 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
984 offsetof(CERT_INFO, rgExtension), 0 },
987 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
988 pDecodePara, pvStructInfo, *pcbStructInfo);
990 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
991 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
992 NULL, NULL);
993 if (ret && pvStructInfo)
995 CERT_INFO *info;
997 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
998 info = *(CERT_INFO **)pvStructInfo;
999 else
1000 info = (CERT_INFO *)pvStructInfo;
1001 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1002 !info->Subject.cbData)
1004 SetLastError(CRYPT_E_ASN1_CORRUPT);
1005 /* Don't need to deallocate, because it should have failed on the
1006 * first pass (and no memory was allocated.)
1008 ret = FALSE;
1012 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1013 return ret;
1016 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1017 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1018 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1020 BOOL ret = FALSE;
1022 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1023 pDecodePara, pvStructInfo, *pcbStructInfo);
1025 __TRY
1027 DWORD size = 0;
1029 /* Unless told not to, first try to decode it as a signed cert. */
1030 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1032 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1034 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1035 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1036 (BYTE *)&signedCert, &size);
1037 if (ret)
1039 size = 0;
1040 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1041 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1042 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1043 pvStructInfo, pcbStructInfo);
1044 LocalFree(signedCert);
1047 /* Failing that, try it as an unsigned cert */
1048 if (!ret)
1050 size = 0;
1051 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1052 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1053 pDecodePara, pvStructInfo, pcbStructInfo);
1056 __EXCEPT_PAGE_FAULT
1058 SetLastError(STATUS_ACCESS_VIOLATION);
1060 __ENDTRY
1062 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1063 return ret;
1066 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1067 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1069 BOOL ret;
1070 struct AsnDecodeSequenceItem items[] = {
1071 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1072 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1073 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1074 { 0, offsetof(CRL_ENTRY, RevocationDate),
1075 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1076 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1077 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1078 offsetof(CRL_ENTRY, rgExtension), 0 },
1080 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1082 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1083 *pcbStructInfo);
1085 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1086 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1087 entry ? entry->SerialNumber.pbData : NULL);
1088 if (ret && entry && !entry->SerialNumber.cbData)
1090 WARN("empty CRL entry serial number\n");
1091 SetLastError(CRYPT_E_ASN1_CORRUPT);
1092 ret = FALSE;
1094 return ret;
1097 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1098 * been set prior to calling.
1100 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1101 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1103 BOOL ret;
1104 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1105 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1106 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1107 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1109 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1110 pvStructInfo, *pcbStructInfo, pcbDecoded);
1112 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1113 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1114 entries ? entries->rgItems : NULL);
1115 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1116 return ret;
1119 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1120 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1121 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1123 struct AsnDecodeSequenceItem items[] = {
1124 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1125 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1126 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1127 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1128 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1129 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1130 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1131 Issuer.pbData) },
1132 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1133 sizeof(FILETIME), FALSE, FALSE, 0 },
1134 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1135 sizeof(FILETIME), TRUE, FALSE, 0 },
1136 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1137 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1138 offsetof(CRL_INFO, rgCRLEntry), 0 },
1139 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1140 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1141 offsetof(CRL_INFO, rgExtension), 0 },
1143 BOOL ret = TRUE;
1145 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1146 pDecodePara, pvStructInfo, *pcbStructInfo);
1148 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1149 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1150 NULL, NULL);
1152 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1153 return ret;
1156 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1157 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1158 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1160 BOOL ret = FALSE;
1162 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1163 pDecodePara, pvStructInfo, *pcbStructInfo);
1165 __TRY
1167 DWORD size = 0;
1169 /* Unless told not to, first try to decode it as a signed crl. */
1170 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1172 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1174 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1175 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1176 (BYTE *)&signedCrl, &size);
1177 if (ret)
1179 size = 0;
1180 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1181 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1182 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1183 pvStructInfo, pcbStructInfo);
1184 LocalFree(signedCrl);
1187 /* Failing that, try it as an unsigned crl */
1188 if (!ret)
1190 size = 0;
1191 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1192 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1193 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1196 __EXCEPT_PAGE_FAULT
1198 SetLastError(STATUS_ACCESS_VIOLATION);
1200 __ENDTRY
1202 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1203 return ret;
1206 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1207 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1209 BOOL ret = TRUE;
1210 DWORD dataLen;
1212 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1213 pvStructInfo, *pcbStructInfo);
1215 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1217 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1218 DWORD bytesNeeded = sizeof(LPSTR);
1220 if (dataLen)
1222 /* The largest possible string for the first two components
1223 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1225 char firstTwo[6];
1226 const BYTE *ptr;
1228 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1229 pbEncoded[1 + lenBytes] / 40,
1230 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1231 * 40);
1232 bytesNeeded += strlen(firstTwo) + 1;
1233 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1234 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1236 /* large enough for ".4000000" */
1237 char str[9];
1238 int val = 0;
1240 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1241 (*ptr & 0x80))
1243 val <<= 7;
1244 val |= *ptr & 0x7f;
1245 ptr++;
1247 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1248 (*ptr & 0x80))
1250 SetLastError(CRYPT_E_ASN1_CORRUPT);
1251 ret = FALSE;
1253 else
1255 val <<= 7;
1256 val |= *ptr++;
1257 snprintf(str, sizeof(str), ".%d", val);
1258 bytesNeeded += strlen(str);
1262 if (pcbDecoded)
1263 *pcbDecoded = 1 + lenBytes + dataLen;
1264 if (!pvStructInfo)
1265 *pcbStructInfo = bytesNeeded;
1266 else if (*pcbStructInfo < bytesNeeded)
1268 *pcbStructInfo = bytesNeeded;
1269 SetLastError(ERROR_MORE_DATA);
1270 ret = FALSE;
1272 else
1274 if (dataLen)
1276 const BYTE *ptr;
1277 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1279 *pszObjId = 0;
1280 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1281 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1282 40) * 40);
1283 pszObjId += strlen(pszObjId);
1284 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1285 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1287 int val = 0;
1289 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1290 (*ptr & 0x80))
1292 val <<= 7;
1293 val |= *ptr & 0x7f;
1294 ptr++;
1296 val <<= 7;
1297 val |= *ptr++;
1298 sprintf(pszObjId, ".%d", val);
1299 pszObjId += strlen(pszObjId);
1302 else
1303 *(LPSTR *)pvStructInfo = NULL;
1304 *pcbStructInfo = bytesNeeded;
1307 return ret;
1310 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1311 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1313 BOOL ret;
1315 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1316 pvStructInfo, *pcbStructInfo);
1318 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1319 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1320 pvStructInfo, pcbStructInfo, pcbDecoded);
1321 else
1323 SetLastError(CRYPT_E_ASN1_BADTAG);
1324 ret = FALSE;
1326 return ret;
1329 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1330 * ahead of time!
1332 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1333 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1335 struct AsnDecodeSequenceItem items[] = {
1336 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1337 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1338 offsetof(CERT_EXTENSION, pszObjId), 0 },
1339 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1340 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1341 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1342 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1343 offsetof(CERT_EXTENSION, Value.pbData) },
1345 BOOL ret = TRUE;
1346 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1348 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1349 *pcbStructInfo);
1351 if (ext)
1352 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1353 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1354 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1355 pcbDecoded, ext ? ext->pszObjId : NULL);
1356 if (ext)
1357 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1358 debugstr_a(ext->pszObjId));
1359 TRACE("returning %d (%08x)\n", ret, GetLastError());
1360 return ret;
1363 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1364 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1365 DWORD *pcbDecoded)
1367 BOOL ret = TRUE;
1368 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1369 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1370 offsetof(CERT_EXTENSION, pszObjId) };
1371 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1373 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1374 pvStructInfo, *pcbStructInfo, pcbDecoded);
1376 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1377 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1378 exts ? exts->rgExtension : NULL);
1379 return ret;
1382 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1383 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1384 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1386 BOOL ret = TRUE;
1388 __TRY
1390 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1391 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1392 if (ret && pvStructInfo)
1394 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1395 pcbStructInfo, *pcbStructInfo);
1396 if (ret)
1398 CERT_EXTENSIONS *exts;
1400 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1401 pvStructInfo = *(BYTE **)pvStructInfo;
1402 exts = (CERT_EXTENSIONS *)pvStructInfo;
1403 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1404 sizeof(CERT_EXTENSIONS));
1405 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1406 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1407 pcbStructInfo, NULL);
1411 __EXCEPT_PAGE_FAULT
1413 SetLastError(STATUS_ACCESS_VIOLATION);
1414 ret = FALSE;
1416 __ENDTRY
1417 return ret;
1420 /* Warning: this assumes the address of value->Value.pbData is already set, in
1421 * order to avoid overwriting memory. (In some cases, it may change it, if it
1422 * doesn't copy anything to memory.) Be sure to set it correctly!
1424 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1425 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1426 DWORD *pcbDecoded)
1428 BOOL ret = TRUE;
1429 DWORD dataLen;
1430 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1432 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1434 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1435 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1437 switch (pbEncoded[0])
1439 case ASN_OCTETSTRING:
1440 valueType = CERT_RDN_OCTET_STRING;
1441 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1442 bytesNeeded += dataLen;
1443 break;
1444 case ASN_NUMERICSTRING:
1445 valueType = CERT_RDN_NUMERIC_STRING;
1446 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1447 bytesNeeded += dataLen;
1448 break;
1449 case ASN_PRINTABLESTRING:
1450 valueType = CERT_RDN_PRINTABLE_STRING;
1451 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1452 bytesNeeded += dataLen;
1453 break;
1454 case ASN_IA5STRING:
1455 valueType = CERT_RDN_IA5_STRING;
1456 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1457 bytesNeeded += dataLen;
1458 break;
1459 case ASN_T61STRING:
1460 valueType = CERT_RDN_T61_STRING;
1461 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1462 bytesNeeded += dataLen;
1463 break;
1464 case ASN_VIDEOTEXSTRING:
1465 valueType = CERT_RDN_VIDEOTEX_STRING;
1466 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1467 bytesNeeded += dataLen;
1468 break;
1469 case ASN_GRAPHICSTRING:
1470 valueType = CERT_RDN_GRAPHIC_STRING;
1471 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1472 bytesNeeded += dataLen;
1473 break;
1474 case ASN_VISIBLESTRING:
1475 valueType = CERT_RDN_VISIBLE_STRING;
1476 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1477 bytesNeeded += dataLen;
1478 break;
1479 case ASN_GENERALSTRING:
1480 valueType = CERT_RDN_GENERAL_STRING;
1481 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1482 bytesNeeded += dataLen;
1483 break;
1484 case ASN_UNIVERSALSTRING:
1485 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1486 SetLastError(CRYPT_E_ASN1_BADTAG);
1487 return FALSE;
1488 case ASN_BMPSTRING:
1489 valueType = CERT_RDN_BMP_STRING;
1490 bytesNeeded += dataLen;
1491 break;
1492 case ASN_UTF8STRING:
1493 valueType = CERT_RDN_UTF8_STRING;
1494 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1495 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1496 break;
1497 default:
1498 SetLastError(CRYPT_E_ASN1_BADTAG);
1499 return FALSE;
1502 if (pcbDecoded)
1503 *pcbDecoded = 1 + lenBytes + dataLen;
1504 if (!value)
1505 *pcbStructInfo = bytesNeeded;
1506 else if (*pcbStructInfo < bytesNeeded)
1508 *pcbStructInfo = bytesNeeded;
1509 SetLastError(ERROR_MORE_DATA);
1510 ret = FALSE;
1512 else
1514 *pcbStructInfo = bytesNeeded;
1515 value->dwValueType = valueType;
1516 if (dataLen)
1518 DWORD i;
1520 assert(value->Value.pbData);
1521 switch (pbEncoded[0])
1523 case ASN_OCTETSTRING:
1524 case ASN_NUMERICSTRING:
1525 case ASN_PRINTABLESTRING:
1526 case ASN_IA5STRING:
1527 case ASN_T61STRING:
1528 case ASN_VIDEOTEXSTRING:
1529 case ASN_GRAPHICSTRING:
1530 case ASN_VISIBLESTRING:
1531 case ASN_GENERALSTRING:
1532 value->Value.cbData = dataLen;
1533 if (dataLen)
1535 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1536 memcpy(value->Value.pbData,
1537 pbEncoded + 1 + lenBytes, dataLen);
1538 else
1539 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1540 lenBytes;
1542 break;
1543 case ASN_BMPSTRING:
1545 LPWSTR str = (LPWSTR)value->Value.pbData;
1547 value->Value.cbData = dataLen;
1548 for (i = 0; i < dataLen / 2; i++)
1549 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1550 pbEncoded[1 + lenBytes + 2 * i + 1];
1551 break;
1553 case ASN_UTF8STRING:
1555 LPWSTR str = (LPWSTR)value->Value.pbData;
1557 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1558 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1559 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1560 break;
1564 else
1566 value->Value.cbData = 0;
1567 value->Value.pbData = NULL;
1571 return ret;
1574 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1575 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1576 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1578 BOOL ret = TRUE;
1580 __TRY
1582 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1583 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1584 if (ret && pvStructInfo)
1586 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1587 pcbStructInfo, *pcbStructInfo);
1588 if (ret)
1590 CERT_NAME_VALUE *value;
1592 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1593 pvStructInfo = *(BYTE **)pvStructInfo;
1594 value = (CERT_NAME_VALUE *)pvStructInfo;
1595 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1596 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1597 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1598 pcbStructInfo, NULL);
1602 __EXCEPT_PAGE_FAULT
1604 SetLastError(STATUS_ACCESS_VIOLATION);
1605 ret = FALSE;
1607 __ENDTRY
1608 return ret;
1611 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1612 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1613 DWORD *pcbDecoded)
1615 BOOL ret = TRUE;
1616 DWORD dataLen;
1617 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1619 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1621 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1622 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1624 switch (pbEncoded[0])
1626 case ASN_NUMERICSTRING:
1627 valueType = CERT_RDN_NUMERIC_STRING;
1628 bytesNeeded += dataLen * 2;
1629 break;
1630 case ASN_PRINTABLESTRING:
1631 valueType = CERT_RDN_PRINTABLE_STRING;
1632 bytesNeeded += dataLen * 2;
1633 break;
1634 case ASN_IA5STRING:
1635 valueType = CERT_RDN_IA5_STRING;
1636 bytesNeeded += dataLen * 2;
1637 break;
1638 case ASN_T61STRING:
1639 valueType = CERT_RDN_T61_STRING;
1640 bytesNeeded += dataLen * 2;
1641 break;
1642 case ASN_VIDEOTEXSTRING:
1643 valueType = CERT_RDN_VIDEOTEX_STRING;
1644 bytesNeeded += dataLen * 2;
1645 break;
1646 case ASN_GRAPHICSTRING:
1647 valueType = CERT_RDN_GRAPHIC_STRING;
1648 bytesNeeded += dataLen * 2;
1649 break;
1650 case ASN_VISIBLESTRING:
1651 valueType = CERT_RDN_VISIBLE_STRING;
1652 bytesNeeded += dataLen * 2;
1653 break;
1654 case ASN_GENERALSTRING:
1655 valueType = CERT_RDN_GENERAL_STRING;
1656 bytesNeeded += dataLen * 2;
1657 break;
1658 case ASN_UNIVERSALSTRING:
1659 valueType = CERT_RDN_UNIVERSAL_STRING;
1660 bytesNeeded += dataLen / 2;
1661 break;
1662 case ASN_BMPSTRING:
1663 valueType = CERT_RDN_BMP_STRING;
1664 bytesNeeded += dataLen;
1665 break;
1666 case ASN_UTF8STRING:
1667 valueType = CERT_RDN_UTF8_STRING;
1668 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1669 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1670 break;
1671 default:
1672 SetLastError(CRYPT_E_ASN1_BADTAG);
1673 return FALSE;
1676 if (pcbDecoded)
1677 *pcbDecoded = 1 + lenBytes + dataLen;
1678 if (!value)
1679 *pcbStructInfo = bytesNeeded;
1680 else if (*pcbStructInfo < bytesNeeded)
1682 *pcbStructInfo = bytesNeeded;
1683 SetLastError(ERROR_MORE_DATA);
1684 ret = FALSE;
1686 else
1688 *pcbStructInfo = bytesNeeded;
1689 value->dwValueType = valueType;
1690 if (dataLen)
1692 DWORD i;
1693 LPWSTR str = (LPWSTR)value->Value.pbData;
1695 assert(value->Value.pbData);
1696 switch (pbEncoded[0])
1698 case ASN_NUMERICSTRING:
1699 case ASN_PRINTABLESTRING:
1700 case ASN_IA5STRING:
1701 case ASN_T61STRING:
1702 case ASN_VIDEOTEXSTRING:
1703 case ASN_GRAPHICSTRING:
1704 case ASN_VISIBLESTRING:
1705 case ASN_GENERALSTRING:
1706 value->Value.cbData = dataLen * 2;
1707 for (i = 0; i < dataLen; i++)
1708 str[i] = pbEncoded[1 + lenBytes + i];
1709 break;
1710 case ASN_UNIVERSALSTRING:
1711 value->Value.cbData = dataLen / 2;
1712 for (i = 0; i < dataLen / 4; i++)
1713 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1714 | pbEncoded[1 + lenBytes + 2 * i + 3];
1715 break;
1716 case ASN_BMPSTRING:
1717 value->Value.cbData = dataLen;
1718 for (i = 0; i < dataLen / 2; i++)
1719 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1720 pbEncoded[1 + lenBytes + 2 * i + 1];
1721 break;
1722 case ASN_UTF8STRING:
1723 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1724 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1725 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1726 break;
1729 else
1731 value->Value.cbData = 0;
1732 value->Value.pbData = NULL;
1736 return ret;
1739 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1740 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1741 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1743 BOOL ret = TRUE;
1745 __TRY
1747 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1748 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1749 if (ret && pvStructInfo)
1751 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1752 pcbStructInfo, *pcbStructInfo);
1753 if (ret)
1755 CERT_NAME_VALUE *value;
1757 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1758 pvStructInfo = *(BYTE **)pvStructInfo;
1759 value = (CERT_NAME_VALUE *)pvStructInfo;
1760 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1761 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1762 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1763 pcbStructInfo, NULL);
1767 __EXCEPT_PAGE_FAULT
1769 SetLastError(STATUS_ACCESS_VIOLATION);
1770 ret = FALSE;
1772 __ENDTRY
1773 return ret;
1776 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1777 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1779 BOOL ret;
1780 struct AsnDecodeSequenceItem items[] = {
1781 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1782 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1783 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1784 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1785 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1786 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1788 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1790 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1791 pvStructInfo, *pcbStructInfo);
1793 if (attr)
1794 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1795 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1796 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1797 attr ? attr->pszObjId : NULL);
1798 if (attr)
1800 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1801 debugstr_a(attr->pszObjId));
1802 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1804 TRACE("returning %d (%08x)\n", ret, GetLastError());
1805 return ret;
1808 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1809 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1811 BOOL ret = TRUE;
1812 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1813 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1814 offsetof(CERT_RDN_ATTR, pszObjId) };
1815 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1817 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1818 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1819 rdn ? rdn->rgRDNAttr : NULL);
1820 return ret;
1823 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1824 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1825 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1827 BOOL ret = TRUE;
1829 __TRY
1831 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1832 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1833 offsetof(CERT_RDN, rgRDNAttr) };
1835 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1836 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1838 __EXCEPT_PAGE_FAULT
1840 SetLastError(STATUS_ACCESS_VIOLATION);
1841 ret = FALSE;
1843 __ENDTRY
1844 return ret;
1847 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1848 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1849 DWORD *pcbDecoded)
1851 BOOL ret;
1852 struct AsnDecodeSequenceItem items[] = {
1853 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1854 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1855 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1856 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1857 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1858 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1860 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1862 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1863 pvStructInfo, *pcbStructInfo);
1865 if (attr)
1866 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1867 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1868 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1869 attr ? attr->pszObjId : NULL);
1870 if (attr)
1872 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1873 debugstr_a(attr->pszObjId));
1874 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1876 TRACE("returning %d (%08x)\n", ret, GetLastError());
1877 return ret;
1880 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1881 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1883 BOOL ret = TRUE;
1884 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1885 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1886 offsetof(CERT_RDN_ATTR, pszObjId) };
1887 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1889 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1890 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1891 rdn ? rdn->rgRDNAttr : NULL);
1892 return ret;
1895 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1896 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1897 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1899 BOOL ret = TRUE;
1901 __TRY
1903 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1904 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1905 offsetof(CERT_RDN, rgRDNAttr) };
1907 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1908 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1910 __EXCEPT_PAGE_FAULT
1912 SetLastError(STATUS_ACCESS_VIOLATION);
1913 ret = FALSE;
1915 __ENDTRY
1916 return ret;
1919 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1920 DWORD *pcbDecoded)
1922 BOOL ret = TRUE, done = FALSE;
1923 DWORD indefiniteNestingLevels = 0, decoded = 0;
1925 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1927 do {
1928 DWORD dataLen;
1930 if (!cbEncoded)
1931 done = TRUE;
1932 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
1933 &dataLen)))
1935 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1937 if (dataLen == CMSG_INDEFINITE_LENGTH)
1939 indefiniteNestingLevels++;
1940 pbEncoded += 1 + lenBytes;
1941 cbEncoded -= 1 + lenBytes;
1942 decoded += 1 + lenBytes;
1943 TRACE("indefiniteNestingLevels = %d\n",
1944 indefiniteNestingLevels);
1946 else
1948 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
1949 indefiniteNestingLevels)
1951 indefiniteNestingLevels--;
1952 TRACE("indefiniteNestingLevels = %d\n",
1953 indefiniteNestingLevels);
1955 pbEncoded += 1 + lenBytes + dataLen;
1956 cbEncoded -= 1 + lenBytes + dataLen;
1957 decoded += 1 + lenBytes + dataLen;
1958 if (!indefiniteNestingLevels)
1959 done = TRUE;
1962 } while (ret && !done);
1963 /* If we haven't found all 0 TLVs, we haven't found the end */
1964 if (ret && indefiniteNestingLevels)
1966 SetLastError(CRYPT_E_ASN1_EOD);
1967 ret = FALSE;
1969 if (ret)
1970 *pcbDecoded = decoded;
1971 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
1972 return ret;
1975 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1976 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1977 DWORD *pcbDecoded)
1979 BOOL ret = TRUE;
1980 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
1982 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1983 pvStructInfo, *pcbStructInfo);
1985 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
1987 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1988 bytesNeeded += encodedLen;
1989 if (!pvStructInfo)
1990 *pcbStructInfo = bytesNeeded;
1991 else if (*pcbStructInfo < bytesNeeded)
1993 SetLastError(ERROR_MORE_DATA);
1994 *pcbStructInfo = bytesNeeded;
1995 ret = FALSE;
1997 else
1999 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
2001 *pcbStructInfo = bytesNeeded;
2002 blob->cbData = encodedLen;
2003 if (encodedLen)
2005 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2006 blob->pbData = (LPBYTE)pbEncoded;
2007 else
2009 assert(blob->pbData);
2010 memcpy(blob->pbData, pbEncoded, blob->cbData);
2013 else
2014 blob->pbData = NULL;
2016 if (pcbDecoded)
2017 *pcbDecoded = encodedLen;
2019 return ret;
2022 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
2023 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2025 BOOL ret;
2026 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
2027 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2028 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
2030 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2031 pvStructInfo, *pcbStructInfo, pcbDecoded);
2033 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2034 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2035 array ? array->rgItems : NULL);
2036 return ret;
2039 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2040 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2042 BOOL ret;
2043 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2044 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2045 CTL_USAGE *usage = (CTL_USAGE *)pvStructInfo;
2047 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2048 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2049 usage ? usage->rgpszUsageIdentifier : NULL);
2050 return ret;
2053 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2054 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2056 struct AsnDecodeSequenceItem items[] = {
2057 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2058 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2059 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2060 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2061 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), FALSE,
2062 TRUE, offsetof(CTL_ENTRY, rgAttribute), 0 },
2064 BOOL ret = TRUE;
2065 CTL_ENTRY *entry = (CTL_ENTRY *)pvStructInfo;
2067 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2068 *pcbStructInfo);
2070 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2071 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2072 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2073 return ret;
2076 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2077 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2079 BOOL ret;
2080 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2081 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2082 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2083 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2085 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2086 pvStructInfo, *pcbStructInfo, pcbDecoded);
2088 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2089 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2090 entries ? entries->rgItems : NULL);
2091 return ret;
2094 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2095 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2096 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2098 BOOL ret = FALSE;
2100 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2101 pDecodePara, pvStructInfo, *pcbStructInfo);
2103 __TRY
2105 struct AsnDecodeSequenceItem items[] = {
2106 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2107 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2108 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2109 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2110 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2111 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2112 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
2113 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2114 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2115 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2116 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2117 { 0, offsetof(CTL_INFO, ThisUpdate),
2118 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2119 0 },
2120 { 0, offsetof(CTL_INFO, NextUpdate),
2121 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2122 0 },
2123 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2124 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2125 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2126 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2127 CRYPT_AsnDecodeCTLEntries, sizeof(struct GenericArray),
2128 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2129 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2130 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
2131 offsetof(CTL_INFO, rgExtension), 0 },
2134 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2135 pDecodePara, pvStructInfo, *pcbStructInfo);
2137 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2138 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2139 pcbStructInfo, NULL, NULL);
2141 __EXCEPT_PAGE_FAULT
2143 SetLastError(STATUS_ACCESS_VIOLATION);
2145 __ENDTRY
2146 return ret;
2149 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2150 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2151 DWORD *pcbDecoded)
2153 BOOL ret;
2154 struct AsnDecodeSequenceItem items[] = {
2155 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2156 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2157 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2158 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2159 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2160 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2162 PCRYPT_SMIME_CAPABILITY capability = (PCRYPT_SMIME_CAPABILITY)pvStructInfo;
2164 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2165 pvStructInfo, *pcbStructInfo);
2167 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2168 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2169 pcbDecoded, capability ? capability->pszObjId : NULL);
2170 TRACE("returning %d\n", ret);
2171 return ret;
2174 static BOOL CRYPT_AsnDecodeSMIMECapabilitiesInternal(const BYTE *pbEncoded,
2175 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2176 DWORD *pcbDecoded)
2178 struct AsnArrayDescriptor arrayDesc = { 0,
2179 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2180 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2181 PCRYPT_SMIME_CAPABILITIES capabilities =
2182 (PCRYPT_SMIME_CAPABILITIES)pvStructInfo;
2183 BOOL ret;
2185 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2186 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2187 capabilities ? capabilities->rgCapability : NULL);
2188 return ret;
2191 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2192 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2193 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2195 BOOL ret = FALSE;
2197 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2198 pDecodePara, pvStructInfo, *pcbStructInfo);
2200 __TRY
2202 DWORD bytesNeeded;
2204 if (!cbEncoded)
2205 SetLastError(CRYPT_E_ASN1_EOD);
2206 else if (pbEncoded[0] != ASN_SEQUENCEOF)
2207 SetLastError(CRYPT_E_ASN1_CORRUPT);
2208 else if ((ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
2209 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2210 NULL)))
2212 if (!pvStructInfo)
2213 *pcbStructInfo = bytesNeeded;
2214 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2215 pvStructInfo, pcbStructInfo, bytesNeeded)))
2217 PCRYPT_SMIME_CAPABILITIES capabilities;
2219 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2220 pvStructInfo = *(BYTE **)pvStructInfo;
2221 capabilities = (PCRYPT_SMIME_CAPABILITIES)pvStructInfo;
2222 capabilities->rgCapability =
2223 (PCRYPT_SMIME_CAPABILITY)((BYTE *)pvStructInfo +
2224 sizeof(CRYPT_SMIME_CAPABILITIES));
2225 ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
2226 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2227 &bytesNeeded, NULL);
2231 __EXCEPT_PAGE_FAULT
2233 SetLastError(STATUS_ACCESS_VIOLATION);
2235 __ENDTRY
2236 TRACE("returning %d\n", ret);
2237 return ret;
2240 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2241 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2242 DWORD *pcbDecoded)
2244 BOOL ret;
2245 struct AsnDecodeSequenceItem items[] = {
2246 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2247 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2248 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2249 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2250 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
2251 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2253 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2255 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2256 pvStructInfo, *pcbStructInfo);
2258 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2259 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2260 pcbDecoded, attr ? attr->pszObjId : NULL);
2261 TRACE("returning %d\n", ret);
2262 return ret;
2265 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2266 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2267 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2269 BOOL ret = FALSE;
2271 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2272 pDecodePara, pvStructInfo, *pcbStructInfo);
2274 __TRY
2276 DWORD bytesNeeded;
2278 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2279 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2280 if (ret)
2282 if (!pvStructInfo)
2283 *pcbStructInfo = bytesNeeded;
2284 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2285 pvStructInfo, pcbStructInfo, bytesNeeded)))
2287 PCRYPT_ATTRIBUTE attr;
2289 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2290 pvStructInfo = *(BYTE **)pvStructInfo;
2291 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2292 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2293 sizeof(CRYPT_ATTRIBUTE));
2294 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2295 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2296 NULL);
2300 __EXCEPT_PAGE_FAULT
2302 SetLastError(STATUS_ACCESS_VIOLATION);
2304 __ENDTRY
2305 TRACE("returning %d\n", ret);
2306 return ret;
2309 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2310 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2311 DWORD *pcbDecoded)
2313 struct AsnArrayDescriptor arrayDesc = { 0,
2314 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2315 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2316 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2317 BOOL ret;
2319 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2320 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2321 NULL);
2322 return ret;
2325 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2326 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2327 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2329 BOOL ret = FALSE;
2331 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2332 pDecodePara, pvStructInfo, *pcbStructInfo);
2334 __TRY
2336 DWORD bytesNeeded;
2338 if (!cbEncoded)
2339 SetLastError(CRYPT_E_ASN1_EOD);
2340 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2341 SetLastError(CRYPT_E_ASN1_CORRUPT);
2342 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2343 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2344 NULL)))
2346 if (!pvStructInfo)
2347 *pcbStructInfo = bytesNeeded;
2348 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2349 pvStructInfo, pcbStructInfo, bytesNeeded)))
2351 PCRYPT_ATTRIBUTES attrs;
2353 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2354 pvStructInfo = *(BYTE **)pvStructInfo;
2355 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2356 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2357 sizeof(CRYPT_ATTRIBUTES));
2358 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2359 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2360 &bytesNeeded, NULL);
2364 __EXCEPT_PAGE_FAULT
2366 SetLastError(STATUS_ACCESS_VIOLATION);
2368 __ENDTRY
2369 TRACE("returning %d\n", ret);
2370 return ret;
2373 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2374 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2376 CRYPT_ALGORITHM_IDENTIFIER *algo =
2377 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2378 BOOL ret = TRUE;
2379 struct AsnDecodeSequenceItem items[] = {
2380 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2381 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2382 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2383 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2384 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2385 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2388 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2389 pvStructInfo, *pcbStructInfo, pcbDecoded);
2391 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2392 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2393 pcbDecoded, algo ? algo->pszObjId : NULL);
2394 if (ret && pvStructInfo)
2396 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2397 debugstr_a(algo->pszObjId));
2399 return ret;
2402 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2403 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2404 DWORD *pcbDecoded)
2406 BOOL ret = TRUE;
2407 struct AsnDecodeSequenceItem items[] = {
2408 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2409 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2410 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2411 Algorithm.pszObjId) },
2412 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2413 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2414 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2416 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2418 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2419 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2420 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2421 return ret;
2424 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2425 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2426 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2428 BOOL ret = TRUE;
2430 __TRY
2432 DWORD bytesNeeded;
2434 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2435 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2437 if (!pvStructInfo)
2438 *pcbStructInfo = bytesNeeded;
2439 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2440 pvStructInfo, pcbStructInfo, bytesNeeded)))
2442 PCERT_PUBLIC_KEY_INFO info;
2444 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2445 pvStructInfo = *(BYTE **)pvStructInfo;
2446 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2447 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2448 sizeof(CERT_PUBLIC_KEY_INFO);
2449 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2450 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2451 &bytesNeeded, NULL);
2455 __EXCEPT_PAGE_FAULT
2457 SetLastError(STATUS_ACCESS_VIOLATION);
2458 ret = FALSE;
2460 __ENDTRY
2461 return ret;
2464 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2465 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2467 BOOL ret;
2469 if (cbEncoded < 3)
2471 SetLastError(CRYPT_E_ASN1_CORRUPT);
2472 return FALSE;
2474 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2476 SetLastError(CRYPT_E_ASN1_CORRUPT);
2477 return FALSE;
2479 if (pbEncoded[1] > 1)
2481 SetLastError(CRYPT_E_ASN1_CORRUPT);
2482 return FALSE;
2484 if (pcbDecoded)
2485 *pcbDecoded = 3;
2486 if (!pvStructInfo)
2488 *pcbStructInfo = sizeof(BOOL);
2489 ret = TRUE;
2491 else if (*pcbStructInfo < sizeof(BOOL))
2493 *pcbStructInfo = sizeof(BOOL);
2494 SetLastError(ERROR_MORE_DATA);
2495 ret = FALSE;
2497 else
2499 *pcbStructInfo = sizeof(BOOL);
2500 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2501 ret = TRUE;
2503 TRACE("returning %d (%08x)\n", ret, GetLastError());
2504 return ret;
2507 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2508 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2510 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2511 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2512 BOOL ret;
2514 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2515 pvStructInfo, *pcbStructInfo);
2517 if (cbEncoded < 2)
2519 SetLastError(CRYPT_E_ASN1_CORRUPT);
2520 return FALSE;
2522 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2523 if (1 + lenBytes > cbEncoded)
2525 SetLastError(CRYPT_E_ASN1_CORRUPT);
2526 return FALSE;
2528 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2530 switch (pbEncoded[0] & ASN_TYPE_MASK)
2532 case 1: /* rfc822Name */
2533 case 2: /* dNSName */
2534 case 6: /* uniformResourceIdentifier */
2535 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2536 break;
2537 case 4: /* directoryName */
2538 case 7: /* iPAddress */
2539 bytesNeeded += dataLen;
2540 break;
2541 case 8: /* registeredID */
2542 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2543 &dataLen, NULL);
2544 if (ret)
2546 /* FIXME: ugly, shouldn't need to know internals of OID decode
2547 * function to use it.
2549 bytesNeeded += dataLen - sizeof(LPSTR);
2551 break;
2552 case 0: /* otherName */
2553 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2554 SetLastError(CRYPT_E_ASN1_BADTAG);
2555 ret = FALSE;
2556 break;
2557 case 3: /* x400Address, unimplemented */
2558 case 5: /* ediPartyName, unimplemented */
2559 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2560 SetLastError(CRYPT_E_ASN1_BADTAG);
2561 ret = FALSE;
2562 break;
2563 default:
2564 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2565 SetLastError(CRYPT_E_ASN1_CORRUPT);
2566 ret = FALSE;
2568 if (ret)
2570 if (pcbDecoded)
2571 *pcbDecoded = 1 + lenBytes + dataLen;
2572 if (!entry)
2573 *pcbStructInfo = bytesNeeded;
2574 else if (*pcbStructInfo < bytesNeeded)
2576 *pcbStructInfo = bytesNeeded;
2577 SetLastError(ERROR_MORE_DATA);
2578 ret = FALSE;
2580 else
2582 *pcbStructInfo = bytesNeeded;
2583 /* MS used values one greater than the asn1 ones.. sigh */
2584 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2585 switch (pbEncoded[0] & ASN_TYPE_MASK)
2587 case 1: /* rfc822Name */
2588 case 2: /* dNSName */
2589 case 6: /* uniformResourceIdentifier */
2591 DWORD i;
2593 for (i = 0; i < dataLen; i++)
2594 entry->u.pwszURL[i] =
2595 (WCHAR)pbEncoded[1 + lenBytes + i];
2596 entry->u.pwszURL[i] = 0;
2597 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2598 debugstr_w(entry->u.pwszURL));
2599 break;
2601 case 4: /* directoryName */
2602 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2603 /* The data are memory-equivalent with the IPAddress case,
2604 * fall-through
2606 case 7: /* iPAddress */
2607 /* The next data pointer is in the pwszURL spot, that is,
2608 * the first 4 bytes. Need to move it to the next spot.
2610 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2611 entry->u.IPAddress.cbData = dataLen;
2612 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2613 dataLen);
2614 break;
2615 case 8: /* registeredID */
2616 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2617 &entry->u.pszRegisteredID, &dataLen, NULL);
2618 break;
2623 return ret;
2626 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2627 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2628 DWORD *pcbDecoded)
2630 BOOL ret = TRUE;
2631 struct AsnArrayDescriptor arrayDesc = { 0,
2632 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2633 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2634 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2636 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2637 pvStructInfo, *pcbStructInfo, pcbDecoded);
2639 if (info)
2640 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2641 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2642 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2643 info ? info->rgAltEntry : NULL);
2644 return ret;
2647 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2648 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2649 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2650 DWORD *pcbDecoded)
2652 BOOL ret;
2654 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2655 pvStructInfo, *pcbStructInfo, pcbDecoded);
2657 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2658 * place.
2660 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2661 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2662 pcbDecoded);
2663 if (ret && pvStructInfo)
2665 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2667 if (blob->cbData)
2669 DWORD i;
2670 BYTE temp;
2672 for (i = 0; i < blob->cbData / 2; i++)
2674 temp = blob->pbData[i];
2675 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2676 blob->pbData[blob->cbData - i - 1] = temp;
2680 TRACE("returning %d (%08x)\n", ret, GetLastError());
2681 return ret;
2684 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2685 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2686 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2688 BOOL ret;
2690 __TRY
2692 struct AsnDecodeSequenceItem items[] = {
2693 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2694 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2695 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2696 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2697 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2698 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2699 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2700 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2701 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2702 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2703 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2706 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2707 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2708 pcbStructInfo, NULL, NULL);
2710 __EXCEPT_PAGE_FAULT
2712 SetLastError(STATUS_ACCESS_VIOLATION);
2713 ret = FALSE;
2715 __ENDTRY
2716 return ret;
2719 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2720 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2721 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2723 BOOL ret;
2725 __TRY
2727 struct AsnDecodeSequenceItem items[] = {
2728 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2729 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2730 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2731 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2732 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2733 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2734 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2735 AuthorityCertIssuer.rgAltEntry), 0 },
2736 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2737 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2738 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2739 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2740 AuthorityCertSerialNumber.pbData), 0 },
2743 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2744 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2745 pcbStructInfo, NULL, NULL);
2747 __EXCEPT_PAGE_FAULT
2749 SetLastError(STATUS_ACCESS_VIOLATION);
2750 ret = FALSE;
2752 __ENDTRY
2753 return ret;
2756 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
2757 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2758 DWORD *pcbDecoded)
2760 struct AsnDecodeSequenceItem items[] = {
2761 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
2762 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
2763 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
2764 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
2765 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
2766 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
2768 CERT_ACCESS_DESCRIPTION *descr = (CERT_ACCESS_DESCRIPTION *)pvStructInfo;
2770 return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2771 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2772 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
2775 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2776 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2777 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2779 BOOL ret;
2781 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2782 pDecodePara, pvStructInfo, *pcbStructInfo);
2784 __TRY
2786 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2787 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
2788 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
2790 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2791 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2793 __EXCEPT_PAGE_FAULT
2795 SetLastError(STATUS_ACCESS_VIOLATION);
2796 ret = FALSE;
2798 __ENDTRY
2799 return ret;
2802 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
2803 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2805 BOOL ret;
2806 DWORD dataLen;
2808 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2809 pvStructInfo, *pcbStructInfo, pcbDecoded);
2811 /* The caller has already checked the tag, no need to check it again.
2812 * Check the outer length is valid:
2814 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
2816 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2817 DWORD innerLen;
2819 pbEncoded += 1 + lenBytes;
2820 cbEncoded -= 1 + lenBytes;
2821 if (dataLen == CMSG_INDEFINITE_LENGTH)
2822 cbEncoded -= 2; /* space for 0 TLV */
2823 /* Check the inner length is valid: */
2824 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
2826 DWORD decodedLen;
2828 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
2829 pvStructInfo, pcbStructInfo, &decodedLen);
2830 if (dataLen == CMSG_INDEFINITE_LENGTH)
2832 if (*(pbEncoded + decodedLen) != 0 ||
2833 *(pbEncoded + decodedLen + 1) != 0)
2835 TRACE("expected 0 TLV, got {%02x,%02x}\n",
2836 *(pbEncoded + decodedLen),
2837 *(pbEncoded + decodedLen + 1));
2838 SetLastError(CRYPT_E_ASN1_CORRUPT);
2839 ret = FALSE;
2841 else
2842 decodedLen += 2;
2844 if (ret && pcbDecoded)
2846 *pcbDecoded = 1 + lenBytes + decodedLen;
2847 TRACE("decoded %d bytes\n", *pcbDecoded);
2851 return ret;
2854 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
2855 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2856 DWORD *pcbDecoded)
2858 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2859 struct AsnDecodeSequenceItem items[] = {
2860 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2861 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2862 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2863 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2864 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2865 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2866 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2868 BOOL ret;
2870 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2871 pvStructInfo, *pcbStructInfo, pcbDecoded);
2873 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2874 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2875 pcbDecoded, info ? info->pszObjId : NULL);
2876 return ret;
2879 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2880 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2881 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2883 BOOL ret = FALSE;
2885 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2886 pDecodePara, pvStructInfo, *pcbStructInfo);
2888 __TRY
2890 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
2891 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2892 if (ret && pvStructInfo)
2894 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2895 pcbStructInfo, *pcbStructInfo);
2896 if (ret)
2898 CRYPT_CONTENT_INFO *info;
2900 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2901 pvStructInfo = *(BYTE **)pvStructInfo;
2902 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2903 info->pszObjId = (LPSTR)((BYTE *)info +
2904 sizeof(CRYPT_CONTENT_INFO));
2905 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
2906 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2907 pcbStructInfo, NULL);
2911 __EXCEPT_PAGE_FAULT
2913 SetLastError(STATUS_ACCESS_VIOLATION);
2915 __ENDTRY
2916 return ret;
2919 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2920 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2921 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2923 BOOL ret;
2924 struct AsnDecodeSequenceItem items[] = {
2925 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2926 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2927 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2928 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2929 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2930 0 },
2931 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2932 CRYPT_AsnDecodePKCSContentInfoInternal,
2933 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2934 ContentInfo.pszObjId), 0 },
2935 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2936 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2937 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2940 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2941 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
2942 NULL, NULL);
2943 return ret;
2946 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2947 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2948 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2950 BOOL ret = TRUE;
2952 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2953 pDecodePara, pvStructInfo, *pcbStructInfo);
2955 __TRY
2957 DWORD bytesNeeded;
2959 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2960 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2962 if (!pvStructInfo)
2963 *pcbStructInfo = bytesNeeded;
2964 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2965 pvStructInfo, pcbStructInfo, bytesNeeded)))
2967 CERT_ALT_NAME_INFO *name;
2969 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2970 pvStructInfo = *(BYTE **)pvStructInfo;
2971 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2972 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2973 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2974 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2975 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2976 &bytesNeeded, NULL);
2980 __EXCEPT_PAGE_FAULT
2982 SetLastError(STATUS_ACCESS_VIOLATION);
2983 ret = FALSE;
2985 __ENDTRY
2986 return ret;
2989 struct PATH_LEN_CONSTRAINT
2991 BOOL fPathLenConstraint;
2992 DWORD dwPathLenConstraint;
2995 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
2996 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2997 DWORD *pcbDecoded)
2999 BOOL ret = TRUE;
3000 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3002 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3003 pvStructInfo, *pcbStructInfo, pcbDecoded);
3005 if (!pvStructInfo)
3007 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3008 &size, pcbDecoded);
3009 *pcbStructInfo = bytesNeeded;
3011 else if (*pcbStructInfo < bytesNeeded)
3013 SetLastError(ERROR_MORE_DATA);
3014 *pcbStructInfo = bytesNeeded;
3015 ret = FALSE;
3017 else
3019 struct PATH_LEN_CONSTRAINT *constraint =
3020 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
3022 *pcbStructInfo = bytesNeeded;
3023 size = sizeof(constraint->dwPathLenConstraint);
3024 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3025 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3026 if (ret)
3027 constraint->fPathLenConstraint = TRUE;
3028 TRACE("got an int, dwPathLenConstraint is %d\n",
3029 constraint->dwPathLenConstraint);
3031 TRACE("returning %d (%08x)\n", ret, GetLastError());
3032 return ret;
3035 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3036 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3037 DWORD *pcbDecoded)
3039 BOOL ret;
3040 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3041 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3042 offsetof(CERT_NAME_BLOB, pbData) };
3043 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
3045 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3046 pvStructInfo, *pcbStructInfo, pcbDecoded);
3048 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3049 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3050 entries ? entries->rgItems : NULL);
3051 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3052 return ret;
3055 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3056 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3057 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3059 BOOL ret;
3061 __TRY
3063 struct AsnDecodeSequenceItem items[] = {
3064 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3065 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3066 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3067 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3068 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3069 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3070 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3071 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3072 sizeof(struct GenericArray), TRUE, TRUE,
3073 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3076 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3077 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3078 pcbStructInfo, NULL, NULL);
3080 __EXCEPT_PAGE_FAULT
3082 SetLastError(STATUS_ACCESS_VIOLATION);
3083 ret = FALSE;
3085 __ENDTRY
3086 return ret;
3089 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3090 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3091 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3093 BOOL ret;
3095 __TRY
3097 struct AsnDecodeSequenceItem items[] = {
3098 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3099 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3100 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3101 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3102 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3105 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3106 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3107 pcbStructInfo, NULL, NULL);
3109 __EXCEPT_PAGE_FAULT
3111 SetLastError(STATUS_ACCESS_VIOLATION);
3112 ret = FALSE;
3114 __ENDTRY
3115 return ret;
3118 #define RSA1_MAGIC 0x31415352
3120 struct DECODED_RSA_PUB_KEY
3122 DWORD pubexp;
3123 CRYPT_INTEGER_BLOB modulus;
3126 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3127 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3128 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3130 BOOL ret;
3132 __TRY
3134 struct AsnDecodeSequenceItem items[] = {
3135 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3136 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3137 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3138 0 },
3139 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3140 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3142 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3143 DWORD size = 0;
3145 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3146 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3147 &size, NULL, NULL);
3148 if (ret)
3150 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3151 decodedKey->modulus.cbData;
3153 if (!pvStructInfo)
3155 *pcbStructInfo = bytesNeeded;
3156 ret = TRUE;
3158 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3159 pvStructInfo, pcbStructInfo, bytesNeeded)))
3161 BLOBHEADER *hdr;
3162 RSAPUBKEY *rsaPubKey;
3164 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3165 pvStructInfo = *(BYTE **)pvStructInfo;
3166 hdr = (BLOBHEADER *)pvStructInfo;
3167 hdr->bType = PUBLICKEYBLOB;
3168 hdr->bVersion = CUR_BLOB_VERSION;
3169 hdr->reserved = 0;
3170 hdr->aiKeyAlg = CALG_RSA_KEYX;
3171 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3172 sizeof(BLOBHEADER));
3173 rsaPubKey->magic = RSA1_MAGIC;
3174 rsaPubKey->pubexp = decodedKey->pubexp;
3175 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3176 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3177 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3178 decodedKey->modulus.cbData);
3180 LocalFree(decodedKey);
3183 __EXCEPT_PAGE_FAULT
3185 SetLastError(STATUS_ACCESS_VIOLATION);
3186 ret = FALSE;
3188 __ENDTRY
3189 return ret;
3192 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
3193 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3194 DWORD *pcbDecoded)
3196 BOOL ret;
3197 DWORD bytesNeeded, dataLen;
3199 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3200 pvStructInfo, *pcbStructInfo, pcbDecoded);
3202 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3204 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3206 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3207 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
3208 else
3209 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
3210 if (pcbDecoded)
3211 *pcbDecoded = 1 + lenBytes + dataLen;
3212 if (!pvStructInfo)
3213 *pcbStructInfo = bytesNeeded;
3214 else if (*pcbStructInfo < bytesNeeded)
3216 SetLastError(ERROR_MORE_DATA);
3217 *pcbStructInfo = bytesNeeded;
3218 ret = FALSE;
3220 else
3222 CRYPT_DATA_BLOB *blob;
3224 *pcbStructInfo = bytesNeeded;
3225 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3226 blob->cbData = dataLen;
3227 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3228 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
3229 else
3231 assert(blob->pbData);
3232 if (blob->cbData)
3233 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
3234 blob->cbData);
3238 return ret;
3241 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
3242 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3243 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3245 BOOL ret;
3247 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3248 pDecodePara, pvStructInfo, *pcbStructInfo);
3250 __TRY
3252 DWORD bytesNeeded;
3254 if (!cbEncoded)
3256 SetLastError(CRYPT_E_ASN1_CORRUPT);
3257 ret = FALSE;
3259 else if (pbEncoded[0] != ASN_OCTETSTRING)
3261 SetLastError(CRYPT_E_ASN1_BADTAG);
3262 ret = FALSE;
3264 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3265 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3267 if (!pvStructInfo)
3268 *pcbStructInfo = bytesNeeded;
3269 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3270 pvStructInfo, pcbStructInfo, bytesNeeded)))
3272 CRYPT_DATA_BLOB *blob;
3274 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3275 pvStructInfo = *(BYTE **)pvStructInfo;
3276 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3277 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
3278 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3279 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3280 &bytesNeeded, NULL);
3284 __EXCEPT_PAGE_FAULT
3286 SetLastError(STATUS_ACCESS_VIOLATION);
3287 ret = FALSE;
3289 __ENDTRY
3290 return ret;
3293 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3294 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3296 BOOL ret;
3298 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3299 pvStructInfo, *pcbStructInfo, pcbDecoded);
3301 if (pbEncoded[0] == ASN_BITSTRING)
3303 DWORD bytesNeeded, dataLen;
3304 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3306 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3308 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3309 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3310 else
3311 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3312 if (pcbDecoded)
3313 *pcbDecoded = 1 + lenBytes + dataLen;
3314 if (!pvStructInfo)
3315 *pcbStructInfo = bytesNeeded;
3316 else if (*pcbStructInfo < bytesNeeded)
3318 *pcbStructInfo = bytesNeeded;
3319 SetLastError(ERROR_MORE_DATA);
3320 ret = FALSE;
3322 else
3324 CRYPT_BIT_BLOB *blob;
3326 *pcbStructInfo = bytesNeeded;
3327 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3328 blob->cbData = dataLen - 1;
3329 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3330 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3332 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3334 else
3336 assert(blob->pbData);
3337 if (blob->cbData)
3339 BYTE mask = 0xff << blob->cUnusedBits;
3341 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3342 blob->cbData);
3343 blob->pbData[blob->cbData - 1] &= mask;
3349 else
3351 SetLastError(CRYPT_E_ASN1_BADTAG);
3352 ret = FALSE;
3354 TRACE("returning %d (%08x)\n", ret, GetLastError());
3355 return ret;
3358 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3359 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3360 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3362 BOOL ret;
3364 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3365 pDecodePara, pvStructInfo, pcbStructInfo);
3367 __TRY
3369 DWORD bytesNeeded;
3371 if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3372 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3374 if (!pvStructInfo)
3375 *pcbStructInfo = bytesNeeded;
3376 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3377 pvStructInfo, pcbStructInfo, bytesNeeded)))
3379 CRYPT_BIT_BLOB *blob;
3381 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3382 pvStructInfo = *(BYTE **)pvStructInfo;
3383 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3384 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3385 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3386 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3387 &bytesNeeded, NULL);
3391 __EXCEPT_PAGE_FAULT
3393 SetLastError(STATUS_ACCESS_VIOLATION);
3394 ret = FALSE;
3396 __ENDTRY
3397 TRACE("returning %d (%08x)\n", ret, GetLastError());
3398 return ret;
3401 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
3402 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3403 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3405 BOOL ret;
3406 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3407 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3408 DWORD size = sizeof(buf);
3410 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3411 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, buf,
3412 &size, pcbDecoded);
3413 if (ret)
3415 if (!pvStructInfo)
3416 *pcbStructInfo = sizeof(int);
3417 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3419 int val, i;
3421 if (blob->pbData[blob->cbData - 1] & 0x80)
3423 /* initialize to a negative value to sign-extend */
3424 val = -1;
3426 else
3427 val = 0;
3428 for (i = 0; i < blob->cbData; i++)
3430 val <<= 8;
3431 val |= blob->pbData[blob->cbData - i - 1];
3433 memcpy(pvStructInfo, &val, sizeof(int));
3436 else if (GetLastError() == ERROR_MORE_DATA)
3437 SetLastError(CRYPT_E_ASN1_LARGE);
3438 return ret;
3441 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3442 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3443 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3445 BOOL ret;
3447 __TRY
3449 DWORD bytesNeeded;
3451 if (!cbEncoded)
3453 SetLastError(CRYPT_E_ASN1_CORRUPT);
3454 ret = FALSE;
3456 else if (pbEncoded[0] != ASN_INTEGER)
3458 SetLastError(CRYPT_E_ASN1_BADTAG);
3459 ret = FALSE;
3461 else
3462 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3463 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3464 if (ret)
3466 if (!pvStructInfo)
3467 *pcbStructInfo = bytesNeeded;
3468 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3469 pvStructInfo, pcbStructInfo, bytesNeeded)))
3471 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3472 pvStructInfo = *(BYTE **)pvStructInfo;
3473 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3474 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3475 &bytesNeeded, NULL);
3479 __EXCEPT_PAGE_FAULT
3481 SetLastError(STATUS_ACCESS_VIOLATION);
3482 ret = FALSE;
3484 __ENDTRY
3485 return ret;
3488 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3489 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3490 DWORD *pcbDecoded)
3492 BOOL ret;
3493 DWORD bytesNeeded, dataLen;
3495 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3497 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3499 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3500 if (pcbDecoded)
3501 *pcbDecoded = 1 + lenBytes + dataLen;
3502 if (!pvStructInfo)
3503 *pcbStructInfo = bytesNeeded;
3504 else if (*pcbStructInfo < bytesNeeded)
3506 *pcbStructInfo = bytesNeeded;
3507 SetLastError(ERROR_MORE_DATA);
3508 ret = FALSE;
3510 else
3512 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3514 *pcbStructInfo = bytesNeeded;
3515 blob->cbData = dataLen;
3516 assert(blob->pbData);
3517 if (blob->cbData)
3519 DWORD i;
3521 for (i = 0; i < blob->cbData; i++)
3523 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3524 dataLen - i - 1);
3529 return ret;
3532 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3533 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3534 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3536 BOOL ret;
3538 __TRY
3540 DWORD bytesNeeded;
3542 if (pbEncoded[0] != ASN_INTEGER)
3544 SetLastError(CRYPT_E_ASN1_BADTAG);
3545 ret = FALSE;
3547 else
3548 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3549 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3550 if (ret)
3552 if (!pvStructInfo)
3553 *pcbStructInfo = bytesNeeded;
3554 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3555 pvStructInfo, pcbStructInfo, bytesNeeded)))
3557 CRYPT_INTEGER_BLOB *blob;
3559 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3560 pvStructInfo = *(BYTE **)pvStructInfo;
3561 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3562 blob->pbData = (BYTE *)pvStructInfo +
3563 sizeof(CRYPT_INTEGER_BLOB);
3564 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3565 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3566 &bytesNeeded, NULL);
3570 __EXCEPT_PAGE_FAULT
3572 SetLastError(STATUS_ACCESS_VIOLATION);
3573 ret = FALSE;
3575 __ENDTRY
3576 return ret;
3579 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3580 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3581 DWORD *pcbDecoded)
3583 BOOL ret;
3585 if (pbEncoded[0] == ASN_INTEGER)
3587 DWORD bytesNeeded, dataLen;
3589 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3591 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3593 if (pcbDecoded)
3594 *pcbDecoded = 1 + lenBytes + dataLen;
3595 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3596 if (!pvStructInfo)
3597 *pcbStructInfo = bytesNeeded;
3598 else if (*pcbStructInfo < bytesNeeded)
3600 *pcbStructInfo = bytesNeeded;
3601 SetLastError(ERROR_MORE_DATA);
3602 ret = FALSE;
3604 else
3606 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3608 *pcbStructInfo = bytesNeeded;
3609 blob->cbData = dataLen;
3610 assert(blob->pbData);
3611 /* remove leading zero byte if it exists */
3612 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3614 blob->cbData--;
3615 blob->pbData++;
3617 if (blob->cbData)
3619 DWORD i;
3621 for (i = 0; i < blob->cbData; i++)
3623 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3624 dataLen - i - 1);
3630 else
3632 SetLastError(CRYPT_E_ASN1_BADTAG);
3633 ret = FALSE;
3635 return ret;
3638 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3639 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3640 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3642 BOOL ret;
3644 __TRY
3646 DWORD bytesNeeded;
3648 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
3649 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3651 if (!pvStructInfo)
3652 *pcbStructInfo = bytesNeeded;
3653 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3654 pvStructInfo, pcbStructInfo, bytesNeeded)))
3656 CRYPT_INTEGER_BLOB *blob;
3658 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3659 pvStructInfo = *(BYTE **)pvStructInfo;
3660 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3661 blob->pbData = (BYTE *)pvStructInfo +
3662 sizeof(CRYPT_INTEGER_BLOB);
3663 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
3664 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3665 &bytesNeeded, NULL);
3669 __EXCEPT_PAGE_FAULT
3671 SetLastError(STATUS_ACCESS_VIOLATION);
3672 ret = FALSE;
3674 __ENDTRY
3675 return ret;
3678 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3679 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3680 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3682 BOOL ret;
3684 if (!pvStructInfo)
3686 *pcbStructInfo = sizeof(int);
3687 return TRUE;
3689 __TRY
3691 if (pbEncoded[0] == ASN_ENUMERATED)
3693 unsigned int val = 0, i;
3695 if (cbEncoded <= 1)
3697 SetLastError(CRYPT_E_ASN1_EOD);
3698 ret = FALSE;
3700 else if (pbEncoded[1] == 0)
3702 SetLastError(CRYPT_E_ASN1_CORRUPT);
3703 ret = FALSE;
3705 else
3707 /* A little strange looking, but we have to accept a sign byte:
3708 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3709 * assuming a small length is okay here, it has to be in short
3710 * form.
3712 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3714 SetLastError(CRYPT_E_ASN1_LARGE);
3715 return FALSE;
3717 for (i = 0; i < pbEncoded[1]; i++)
3719 val <<= 8;
3720 val |= pbEncoded[2 + i];
3722 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3723 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3725 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3726 pvStructInfo = *(BYTE **)pvStructInfo;
3727 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3731 else
3733 SetLastError(CRYPT_E_ASN1_BADTAG);
3734 ret = FALSE;
3737 __EXCEPT_PAGE_FAULT
3739 SetLastError(STATUS_ACCESS_VIOLATION);
3740 ret = FALSE;
3742 __ENDTRY
3743 return ret;
3746 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3747 * if it fails.
3749 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3750 do { \
3751 BYTE i; \
3753 (word) = 0; \
3754 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3756 if (!isdigit(*(pbEncoded))) \
3758 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3759 ret = FALSE; \
3761 else \
3763 (word) *= 10; \
3764 (word) += *(pbEncoded)++ - '0'; \
3767 } while (0)
3769 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3770 SYSTEMTIME *sysTime)
3772 BOOL ret = TRUE;
3774 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3776 WORD hours, minutes = 0;
3777 BYTE sign = *pbEncoded++;
3779 len--;
3780 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3781 if (ret && hours >= 24)
3783 SetLastError(CRYPT_E_ASN1_CORRUPT);
3784 ret = FALSE;
3786 else if (len >= 2)
3788 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3789 if (ret && minutes >= 60)
3791 SetLastError(CRYPT_E_ASN1_CORRUPT);
3792 ret = FALSE;
3795 if (ret)
3797 if (sign == '+')
3799 sysTime->wHour += hours;
3800 sysTime->wMinute += minutes;
3802 else
3804 if (hours > sysTime->wHour)
3806 sysTime->wDay--;
3807 sysTime->wHour = 24 - (hours - sysTime->wHour);
3809 else
3810 sysTime->wHour -= hours;
3811 if (minutes > sysTime->wMinute)
3813 sysTime->wHour--;
3814 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3816 else
3817 sysTime->wMinute -= minutes;
3821 return ret;
3824 #define MIN_ENCODED_TIME_LENGTH 10
3826 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3827 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3828 DWORD *pcbDecoded)
3830 BOOL ret = FALSE;
3832 if (pbEncoded[0] == ASN_UTCTIME)
3834 if (cbEncoded <= 1)
3835 SetLastError(CRYPT_E_ASN1_EOD);
3836 else if (pbEncoded[1] > 0x7f)
3838 /* long-form date strings really can't be valid */
3839 SetLastError(CRYPT_E_ASN1_CORRUPT);
3841 else
3843 SYSTEMTIME sysTime = { 0 };
3844 BYTE len = pbEncoded[1];
3846 if (len < MIN_ENCODED_TIME_LENGTH)
3847 SetLastError(CRYPT_E_ASN1_CORRUPT);
3848 else
3850 ret = TRUE;
3851 if (pcbDecoded)
3852 *pcbDecoded = 2 + len;
3853 pbEncoded += 2;
3854 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3855 if (sysTime.wYear >= 50)
3856 sysTime.wYear += 1900;
3857 else
3858 sysTime.wYear += 2000;
3859 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3860 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3861 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3862 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3863 if (ret && len > 0)
3865 if (len >= 2 && isdigit(*pbEncoded) &&
3866 isdigit(*(pbEncoded + 1)))
3867 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3868 sysTime.wSecond);
3869 else if (isdigit(*pbEncoded))
3870 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3871 sysTime.wSecond);
3872 if (ret)
3873 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3874 &sysTime);
3876 if (ret)
3878 if (!pvStructInfo)
3879 *pcbStructInfo = sizeof(FILETIME);
3880 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3881 sizeof(FILETIME))))
3882 ret = SystemTimeToFileTime(&sysTime,
3883 (FILETIME *)pvStructInfo);
3888 else
3889 SetLastError(CRYPT_E_ASN1_BADTAG);
3890 return ret;
3893 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3894 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3895 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3897 BOOL ret = FALSE;
3899 __TRY
3901 DWORD bytesNeeded;
3903 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3904 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3905 if (ret)
3907 if (!pvStructInfo)
3908 *pcbStructInfo = bytesNeeded;
3909 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3910 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3912 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3913 pvStructInfo = *(BYTE **)pvStructInfo;
3914 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3915 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3916 &bytesNeeded, NULL);
3920 __EXCEPT_PAGE_FAULT
3922 SetLastError(STATUS_ACCESS_VIOLATION);
3924 __ENDTRY
3925 return ret;
3928 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3929 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3930 DWORD *pcbDecoded)
3932 BOOL ret = FALSE;
3934 if (pbEncoded[0] == ASN_GENERALTIME)
3936 if (cbEncoded <= 1)
3937 SetLastError(CRYPT_E_ASN1_EOD);
3938 else if (pbEncoded[1] > 0x7f)
3940 /* long-form date strings really can't be valid */
3941 SetLastError(CRYPT_E_ASN1_CORRUPT);
3943 else
3945 BYTE len = pbEncoded[1];
3947 if (len < MIN_ENCODED_TIME_LENGTH)
3948 SetLastError(CRYPT_E_ASN1_CORRUPT);
3949 else
3951 SYSTEMTIME sysTime = { 0 };
3953 ret = TRUE;
3954 if (pcbDecoded)
3955 *pcbDecoded = 2 + len;
3956 pbEncoded += 2;
3957 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3958 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3959 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3960 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3961 if (ret && len > 0)
3963 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3964 sysTime.wMinute);
3965 if (ret && len > 0)
3966 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3967 sysTime.wSecond);
3968 if (ret && len > 0 && (*pbEncoded == '.' ||
3969 *pbEncoded == ','))
3971 BYTE digits;
3973 pbEncoded++;
3974 len--;
3975 /* workaround macro weirdness */
3976 digits = min(len, 3);
3977 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3978 sysTime.wMilliseconds);
3980 if (ret)
3981 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3982 &sysTime);
3984 if (ret)
3986 if (!pvStructInfo)
3987 *pcbStructInfo = sizeof(FILETIME);
3988 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3989 sizeof(FILETIME))))
3990 ret = SystemTimeToFileTime(&sysTime,
3991 (FILETIME *)pvStructInfo);
3996 else
3997 SetLastError(CRYPT_E_ASN1_BADTAG);
3998 return ret;
4001 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4002 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4003 DWORD *pcbDecoded)
4005 BOOL ret;
4006 InternalDecodeFunc decode = NULL;
4008 if (pbEncoded[0] == ASN_UTCTIME)
4009 decode = CRYPT_AsnDecodeUtcTimeInternal;
4010 else if (pbEncoded[0] == ASN_GENERALTIME)
4011 decode = CRYPT_AsnDecodeGeneralizedTime;
4012 if (decode)
4013 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
4014 pcbStructInfo, pcbDecoded);
4015 else
4017 SetLastError(CRYPT_E_ASN1_BADTAG);
4018 ret = FALSE;
4020 return ret;
4023 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
4024 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4025 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4027 BOOL ret;
4029 __TRY
4031 DWORD bytesNeeded;
4033 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4034 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4035 if (ret)
4037 if (!pvStructInfo)
4038 *pcbStructInfo = bytesNeeded;
4039 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4040 pvStructInfo, pcbStructInfo, bytesNeeded)))
4042 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4043 pvStructInfo = *(BYTE **)pvStructInfo;
4044 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4045 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4046 &bytesNeeded, NULL);
4050 __EXCEPT_PAGE_FAULT
4052 SetLastError(STATUS_ACCESS_VIOLATION);
4053 ret = FALSE;
4055 __ENDTRY
4056 return ret;
4059 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
4060 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4061 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4063 BOOL ret = TRUE;
4065 __TRY
4067 if (pbEncoded[0] == ASN_SEQUENCEOF)
4069 DWORD bytesNeeded, dataLen, remainingLen, cValue;
4071 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4073 BYTE lenBytes;
4074 const BYTE *ptr;
4076 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4077 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
4078 cValue = 0;
4079 ptr = pbEncoded + 1 + lenBytes;
4080 remainingLen = dataLen;
4081 while (ret && remainingLen)
4083 DWORD nextLen;
4085 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4086 if (ret)
4088 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4090 remainingLen -= 1 + nextLenBytes + nextLen;
4091 ptr += 1 + nextLenBytes + nextLen;
4092 bytesNeeded += sizeof(CRYPT_DER_BLOB);
4093 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
4094 bytesNeeded += 1 + nextLenBytes + nextLen;
4095 cValue++;
4098 if (ret)
4100 CRYPT_SEQUENCE_OF_ANY *seq;
4101 BYTE *nextPtr;
4102 DWORD i;
4104 if (!pvStructInfo)
4105 *pcbStructInfo = bytesNeeded;
4106 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4107 pvStructInfo, pcbStructInfo, bytesNeeded)))
4109 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4110 pvStructInfo = *(BYTE **)pvStructInfo;
4111 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
4112 seq->cValue = cValue;
4113 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
4114 sizeof(*seq));
4115 nextPtr = (BYTE *)seq->rgValue +
4116 cValue * sizeof(CRYPT_DER_BLOB);
4117 ptr = pbEncoded + 1 + lenBytes;
4118 remainingLen = dataLen;
4119 i = 0;
4120 while (ret && remainingLen)
4122 DWORD nextLen;
4124 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4125 if (ret)
4127 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4129 seq->rgValue[i].cbData = 1 + nextLenBytes +
4130 nextLen;
4131 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4132 seq->rgValue[i].pbData = (BYTE *)ptr;
4133 else
4135 seq->rgValue[i].pbData = nextPtr;
4136 memcpy(nextPtr, ptr, 1 + nextLenBytes +
4137 nextLen);
4138 nextPtr += 1 + nextLenBytes + nextLen;
4140 remainingLen -= 1 + nextLenBytes + nextLen;
4141 ptr += 1 + nextLenBytes + nextLen;
4142 i++;
4149 else
4151 SetLastError(CRYPT_E_ASN1_BADTAG);
4152 ret = FALSE;
4155 __EXCEPT_PAGE_FAULT
4157 SetLastError(STATUS_ACCESS_VIOLATION);
4158 ret = FALSE;
4160 __ENDTRY
4161 return ret;
4164 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4165 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4166 DWORD *pcbDecoded)
4168 BOOL ret;
4170 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
4172 DWORD bytesNeeded, dataLen;
4174 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4176 struct AsnArrayDescriptor arrayDesc = {
4177 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
4178 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
4179 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
4180 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4181 DWORD nameLen;
4183 if (dataLen)
4185 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4186 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4187 0, NULL, NULL, &nameLen, NULL, NULL);
4188 /* The CERT_ALT_NAME_INFO's size is included by CRYPT_AsnDecodeArray
4189 * as the sizeof(struct GenericArray), so don't include it in the
4190 * total bytes needed.
4192 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
4193 sizeof(CERT_ALT_NAME_INFO);
4195 else
4196 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
4197 if (pcbDecoded)
4198 *pcbDecoded = 1 + lenBytes + dataLen;
4199 if (!pvStructInfo)
4200 *pcbStructInfo = bytesNeeded;
4201 else if (*pcbStructInfo < bytesNeeded)
4203 *pcbStructInfo = bytesNeeded;
4204 SetLastError(ERROR_MORE_DATA);
4205 ret = FALSE;
4207 else
4209 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
4211 *pcbStructInfo = bytesNeeded;
4212 if (dataLen)
4214 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
4215 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4216 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4217 0, NULL, &name->u.FullName, &nameLen, NULL,
4218 name->u.FullName.rgAltEntry);
4220 else
4221 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
4225 else
4227 SetLastError(CRYPT_E_ASN1_BADTAG);
4228 ret = FALSE;
4230 return ret;
4233 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
4234 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4236 struct AsnDecodeSequenceItem items[] = {
4237 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
4238 DistPointName), CRYPT_AsnDecodeDistPointName,
4239 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
4240 DistPointName.u.FullName.rgAltEntry), 0 },
4241 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
4242 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
4243 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
4244 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
4245 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
4246 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
4248 BOOL ret;
4250 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4251 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4252 pcbDecoded, NULL);
4253 return ret;
4256 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
4257 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4258 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4260 BOOL ret;
4262 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4263 pDecodePara, pvStructInfo, *pcbStructInfo);
4265 __TRY
4267 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4268 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
4269 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
4271 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4272 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4274 __EXCEPT_PAGE_FAULT
4276 SetLastError(STATUS_ACCESS_VIOLATION);
4277 ret = FALSE;
4279 __ENDTRY
4280 return ret;
4283 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
4284 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4285 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4287 BOOL ret;
4289 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4290 pDecodePara, pvStructInfo, *pcbStructInfo);
4292 __TRY
4294 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4295 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4297 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4298 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4300 __EXCEPT_PAGE_FAULT
4302 SetLastError(STATUS_ACCESS_VIOLATION);
4303 ret = FALSE;
4305 __ENDTRY
4306 return ret;
4309 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4310 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4311 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4313 BOOL ret;
4315 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4316 pDecodePara, pvStructInfo, *pcbStructInfo);
4318 __TRY
4320 struct AsnDecodeSequenceItem items[] = {
4321 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4322 DistPointName), CRYPT_AsnDecodeDistPointName,
4323 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4324 offsetof(CRL_ISSUING_DIST_POINT,
4325 DistPointName.u.FullName.rgAltEntry), 0 },
4326 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4327 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4328 FALSE, 0 },
4329 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4330 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4331 FALSE, 0 },
4332 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4333 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4334 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4335 OnlySomeReasonFlags.pbData), 0 },
4336 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4337 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4340 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4341 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4342 pcbStructInfo, NULL, NULL);
4344 __EXCEPT_PAGE_FAULT
4346 SetLastError(STATUS_ACCESS_VIOLATION);
4347 ret = FALSE;
4349 __ENDTRY
4350 return ret;
4353 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
4354 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4355 DWORD *pcbDecoded)
4357 BOOL ret = FALSE;
4359 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4360 pvStructInfo, *pcbStructInfo, pcbDecoded);
4362 if (!cbEncoded)
4364 SetLastError(CRYPT_E_ASN1_EOD);
4365 return FALSE;
4367 if (pbEncoded[0] != (ASN_CONTEXT | 1))
4369 SetLastError(CRYPT_E_ASN1_BADTAG);
4370 return FALSE;
4372 /* The BOOL is implicit: if the integer is present, then it's TRUE */
4373 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
4374 pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo,
4375 pcbDecoded);
4376 if (ret && pvStructInfo)
4377 *(BOOL *)pvStructInfo = TRUE;
4378 TRACE("returning %d\n", ret);
4379 return ret;
4382 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
4383 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4384 DWORD *pcbDecoded)
4386 BOOL ret;
4387 struct AsnDecodeSequenceItem items[] = {
4388 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
4389 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
4390 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
4391 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
4392 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
4393 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
4394 CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0,
4395 0 },
4397 CERT_GENERAL_SUBTREE *subtree = (CERT_GENERAL_SUBTREE *)pvStructInfo;
4399 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4400 pvStructInfo, *pcbStructInfo, pcbDecoded);
4402 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4403 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4404 pcbDecoded, subtree ? (BYTE *)subtree->Base.u.pwszURL : NULL);
4405 if (pcbDecoded)
4407 TRACE("%d\n", *pcbDecoded);
4408 if (*pcbDecoded < cbEncoded)
4409 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
4410 *(pbEncoded + *pcbDecoded + 1));
4412 TRACE("returning %d\n", ret);
4413 return ret;
4416 static BOOL CRYPT_AsnDecodeSubtreeArray(const BYTE *pbEncoded,
4417 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4418 DWORD *pcbDecoded)
4420 BOOL ret = TRUE;
4421 struct AsnArrayDescriptor arrayDesc = { 0,
4422 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4423 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4424 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4426 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4427 pvStructInfo, *pcbStructInfo, pcbDecoded);
4429 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4430 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4431 array ? array->rgItems : NULL);
4432 return ret;
4436 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
4437 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4438 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4440 BOOL ret = FALSE;
4442 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4443 pDecodePara, pvStructInfo, *pcbStructInfo);
4445 __TRY
4447 struct AsnDecodeSequenceItem items[] = {
4448 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4449 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
4450 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4451 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
4452 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
4453 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4454 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4455 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
4458 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4459 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4460 pcbStructInfo, NULL, NULL);
4462 __EXCEPT_PAGE_FAULT
4464 SetLastError(STATUS_ACCESS_VIOLATION);
4466 __ENDTRY
4467 return ret;
4470 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
4471 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4472 DWORD *pcbDecoded)
4474 BOOL ret;
4475 struct AsnDecodeSequenceItem items[] = {
4476 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4477 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4478 Issuer.pbData) },
4479 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4480 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4481 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4483 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4484 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4486 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4487 pvStructInfo, *pcbStructInfo, pcbDecoded);
4489 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4490 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4491 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4492 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4494 SetLastError(CRYPT_E_ASN1_CORRUPT);
4495 ret = FALSE;
4497 TRACE("returning %d\n", ret);
4498 return ret;
4501 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4502 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4503 DWORD *pcbDecoded)
4505 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4506 struct AsnDecodeSequenceItem items[] = {
4507 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4508 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4509 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4510 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4511 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4512 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4513 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4514 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4515 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4516 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4517 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4518 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4519 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4520 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4521 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4522 HashEncryptionAlgorithm.pszObjId), 0 },
4523 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4524 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4525 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4526 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4527 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4528 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4529 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4531 BOOL ret;
4533 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4534 pvStructInfo, *pcbStructInfo);
4536 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4537 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4538 pcbDecoded, info ? info->Issuer.pbData : NULL);
4539 return ret;
4542 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4543 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4544 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4546 BOOL ret = FALSE;
4548 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4549 pDecodePara, pvStructInfo, *pcbStructInfo);
4551 __TRY
4553 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4554 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4555 if (ret && pvStructInfo)
4557 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4558 pcbStructInfo, *pcbStructInfo);
4559 if (ret)
4561 CMSG_SIGNER_INFO *info;
4563 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4564 pvStructInfo = *(BYTE **)pvStructInfo;
4565 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4566 info->Issuer.pbData = ((BYTE *)info +
4567 sizeof(CMSG_SIGNER_INFO));
4568 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4569 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4570 pcbStructInfo, NULL);
4574 __EXCEPT_PAGE_FAULT
4576 SetLastError(STATUS_ACCESS_VIOLATION);
4578 __ENDTRY
4579 TRACE("returning %d\n", ret);
4580 return ret;
4583 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
4584 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4585 DWORD *pcbDecoded)
4587 CERT_ID *id = (CERT_ID *)pvStructInfo;
4588 BOOL ret = FALSE;
4590 if (*pbEncoded == ASN_SEQUENCEOF)
4592 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
4593 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
4594 if (ret)
4596 if (id)
4597 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
4598 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
4599 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4600 sizeof(CERT_ISSUER_SERIAL_NUMBER);
4601 else
4602 *pcbStructInfo = sizeof(CERT_ID);
4605 else if (*pbEncoded == (ASN_CONTEXT | 0))
4607 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
4608 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
4609 if (ret)
4611 if (id)
4612 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
4613 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
4614 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4615 sizeof(CRYPT_DATA_BLOB);
4616 else
4617 *pcbStructInfo = sizeof(CERT_ID);
4620 else
4621 SetLastError(CRYPT_E_ASN1_BADTAG);
4622 return ret;
4625 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
4626 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4627 DWORD *pcbDecoded)
4629 CMSG_CMS_SIGNER_INFO *info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4630 struct AsnDecodeSequenceItem items[] = {
4631 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
4632 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4633 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
4634 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
4635 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
4636 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
4637 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4638 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4639 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4640 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
4641 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4642 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4643 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
4644 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4645 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
4646 HashEncryptionAlgorithm.pszObjId), 0 },
4647 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
4648 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4649 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
4650 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4651 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
4652 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4653 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4655 BOOL ret;
4657 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4658 pvStructInfo, *pcbStructInfo);
4660 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4661 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4662 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
4663 return ret;
4666 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
4667 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4668 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4670 BOOL ret = FALSE;
4672 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4673 pDecodePara, pvStructInfo, *pcbStructInfo);
4675 __TRY
4677 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
4678 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4679 if (ret && pvStructInfo)
4681 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4682 pcbStructInfo, *pcbStructInfo);
4683 if (ret)
4685 CMSG_CMS_SIGNER_INFO *info;
4687 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4688 pvStructInfo = *(BYTE **)pvStructInfo;
4689 info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4690 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
4691 sizeof(CMSG_CMS_SIGNER_INFO));
4692 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
4693 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4694 pcbStructInfo, NULL);
4698 __EXCEPT_PAGE_FAULT
4700 SetLastError(STATUS_ACCESS_VIOLATION);
4702 __ENDTRY
4703 TRACE("returning %d\n", ret);
4704 return ret;
4707 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
4708 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4710 BOOL ret;
4711 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4712 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
4713 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
4714 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4716 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4717 pvStructInfo, *pcbStructInfo, pcbDecoded);
4719 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4720 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4721 array ? array->rgItems : NULL);
4722 return ret;
4725 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4726 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4727 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4729 BOOL ret = FALSE;
4730 struct AsnDecodeSequenceItem items[] = {
4731 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4732 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4733 /* Placeholder for the hash algorithms - redundant with those in the
4734 * signers, so just ignore them.
4736 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4737 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4738 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4739 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4740 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4741 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4742 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4743 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4744 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4745 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4746 sizeof(struct GenericArray), TRUE, TRUE,
4747 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4748 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4749 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4750 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4753 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4754 pDecodePara, signedInfo, *pcbSignedInfo);
4756 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4757 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
4758 NULL, NULL);
4759 TRACE("returning %d\n", ret);
4760 return ret;
4763 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4764 LPCSTR lpszStructType)
4766 CryptDecodeObjectExFunc decodeFunc = NULL;
4768 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4769 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4771 SetLastError(ERROR_FILE_NOT_FOUND);
4772 return NULL;
4774 if (!HIWORD(lpszStructType))
4776 switch (LOWORD(lpszStructType))
4778 case LOWORD(X509_CERT):
4779 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4780 break;
4781 case LOWORD(X509_CERT_TO_BE_SIGNED):
4782 decodeFunc = CRYPT_AsnDecodeCert;
4783 break;
4784 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4785 decodeFunc = CRYPT_AsnDecodeCRL;
4786 break;
4787 case LOWORD(X509_EXTENSIONS):
4788 decodeFunc = CRYPT_AsnDecodeExtensions;
4789 break;
4790 case LOWORD(X509_NAME_VALUE):
4791 decodeFunc = CRYPT_AsnDecodeNameValue;
4792 break;
4793 case LOWORD(X509_NAME):
4794 decodeFunc = CRYPT_AsnDecodeName;
4795 break;
4796 case LOWORD(X509_PUBLIC_KEY_INFO):
4797 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4798 break;
4799 case LOWORD(X509_AUTHORITY_KEY_ID):
4800 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4801 break;
4802 case LOWORD(X509_ALTERNATE_NAME):
4803 decodeFunc = CRYPT_AsnDecodeAltName;
4804 break;
4805 case LOWORD(X509_BASIC_CONSTRAINTS):
4806 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4807 break;
4808 case LOWORD(X509_BASIC_CONSTRAINTS2):
4809 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4810 break;
4811 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4812 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4813 break;
4814 case LOWORD(X509_UNICODE_NAME):
4815 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4816 break;
4817 case LOWORD(PKCS_ATTRIBUTE):
4818 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4819 break;
4820 case LOWORD(X509_UNICODE_NAME_VALUE):
4821 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4822 break;
4823 case LOWORD(X509_OCTET_STRING):
4824 decodeFunc = CRYPT_AsnDecodeOctets;
4825 break;
4826 case LOWORD(X509_BITS):
4827 case LOWORD(X509_KEY_USAGE):
4828 decodeFunc = CRYPT_AsnDecodeBits;
4829 break;
4830 case LOWORD(X509_INTEGER):
4831 decodeFunc = CRYPT_AsnDecodeInt;
4832 break;
4833 case LOWORD(X509_MULTI_BYTE_INTEGER):
4834 decodeFunc = CRYPT_AsnDecodeInteger;
4835 break;
4836 case LOWORD(X509_MULTI_BYTE_UINT):
4837 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4838 break;
4839 case LOWORD(X509_ENUMERATED):
4840 decodeFunc = CRYPT_AsnDecodeEnumerated;
4841 break;
4842 case LOWORD(X509_CHOICE_OF_TIME):
4843 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4844 break;
4845 case LOWORD(X509_AUTHORITY_KEY_ID2):
4846 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4847 break;
4848 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4849 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
4850 break;
4851 case LOWORD(PKCS_CONTENT_INFO):
4852 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4853 break;
4854 case LOWORD(X509_SEQUENCE_OF_ANY):
4855 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4856 break;
4857 case LOWORD(PKCS_UTC_TIME):
4858 decodeFunc = CRYPT_AsnDecodeUtcTime;
4859 break;
4860 case LOWORD(X509_CRL_DIST_POINTS):
4861 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4862 break;
4863 case LOWORD(X509_ENHANCED_KEY_USAGE):
4864 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4865 break;
4866 case LOWORD(PKCS_CTL):
4867 decodeFunc = CRYPT_AsnDecodeCTL;
4868 break;
4869 case LOWORD(PKCS_SMIME_CAPABILITIES):
4870 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
4871 break;
4872 case LOWORD(PKCS_ATTRIBUTES):
4873 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4874 break;
4875 case LOWORD(X509_ISSUING_DIST_POINT):
4876 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4877 break;
4878 case LOWORD(X509_NAME_CONSTRAINTS):
4879 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4880 break;
4881 case LOWORD(PKCS7_SIGNER_INFO):
4882 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4883 break;
4884 case LOWORD(CMS_SIGNER_INFO):
4885 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
4886 break;
4889 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4890 decodeFunc = CRYPT_AsnDecodeExtensions;
4891 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4892 decodeFunc = CRYPT_AsnDecodeUtcTime;
4893 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4894 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
4895 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4896 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4897 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4898 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4899 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4900 decodeFunc = CRYPT_AsnDecodeEnumerated;
4901 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4902 decodeFunc = CRYPT_AsnDecodeBits;
4903 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4904 decodeFunc = CRYPT_AsnDecodeOctets;
4905 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4906 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4907 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4908 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4909 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4910 decodeFunc = CRYPT_AsnDecodeAltName;
4911 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4912 decodeFunc = CRYPT_AsnDecodeAltName;
4913 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4914 decodeFunc = CRYPT_AsnDecodeAltName;
4915 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4916 decodeFunc = CRYPT_AsnDecodeAltName;
4917 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4918 decodeFunc = CRYPT_AsnDecodeAltName;
4919 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4920 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4921 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4922 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4923 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4924 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4925 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4926 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4927 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4928 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
4929 else if (!strcmp(lpszStructType, szOID_CTL))
4930 decodeFunc = CRYPT_AsnDecodeCTL;
4931 return decodeFunc;
4934 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4935 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4937 static HCRYPTOIDFUNCSET set = NULL;
4938 CryptDecodeObjectFunc decodeFunc = NULL;
4940 if (!set)
4941 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4942 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4943 (void **)&decodeFunc, hFunc);
4944 return decodeFunc;
4947 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4948 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4950 static HCRYPTOIDFUNCSET set = NULL;
4951 CryptDecodeObjectExFunc decodeFunc = NULL;
4953 if (!set)
4954 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4955 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4956 (void **)&decodeFunc, hFunc);
4957 return decodeFunc;
4960 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4961 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4962 DWORD *pcbStructInfo)
4964 BOOL ret = FALSE;
4965 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4966 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4967 HCRYPTOIDFUNCADDR hFunc = NULL;
4969 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4970 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4971 pvStructInfo, pcbStructInfo);
4973 if (!pvStructInfo && !pcbStructInfo)
4975 SetLastError(ERROR_INVALID_PARAMETER);
4976 return FALSE;
4978 if (!cbEncoded)
4980 SetLastError(CRYPT_E_ASN1_EOD);
4981 return FALSE;
4983 if (cbEncoded > MAX_ENCODED_LEN)
4985 SetLastError(CRYPT_E_ASN1_LARGE);
4986 return FALSE;
4989 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4990 lpszStructType)))
4992 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4993 debugstr_a(lpszStructType));
4994 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4995 lpszStructType, &hFunc);
4996 if (!pCryptDecodeObject)
4997 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4998 lpszStructType, &hFunc);
5000 if (pCryptDecodeObject)
5001 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5002 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5003 else if (pCryptDecodeObjectEx)
5004 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
5005 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
5006 pvStructInfo, pcbStructInfo);
5007 if (hFunc)
5008 CryptFreeOIDFunctionAddress(hFunc, 0);
5009 TRACE_(crypt)("returning %d\n", ret);
5010 return ret;
5013 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5014 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5015 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5017 BOOL ret = FALSE;
5018 CryptDecodeObjectExFunc decodeFunc;
5019 HCRYPTOIDFUNCADDR hFunc = NULL;
5021 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
5022 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5023 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5025 if (!pvStructInfo && !pcbStructInfo)
5027 SetLastError(ERROR_INVALID_PARAMETER);
5028 return FALSE;
5030 if (!cbEncoded)
5032 SetLastError(CRYPT_E_ASN1_EOD);
5033 return FALSE;
5035 if (cbEncoded > MAX_ENCODED_LEN)
5037 SetLastError(CRYPT_E_ASN1_LARGE);
5038 return FALSE;
5041 SetLastError(NOERROR);
5042 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5043 *(BYTE **)pvStructInfo = NULL;
5044 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
5045 if (!decodeFunc)
5047 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5048 debugstr_a(lpszStructType));
5049 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
5050 &hFunc);
5052 if (decodeFunc)
5053 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5054 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5055 else
5057 CryptDecodeObjectFunc pCryptDecodeObject =
5058 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
5060 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
5061 * directly, as that could cause an infinite loop.
5063 if (pCryptDecodeObject)
5065 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5067 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5068 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
5069 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5070 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
5071 ret = pCryptDecodeObject(dwCertEncodingType,
5072 lpszStructType, pbEncoded, cbEncoded, dwFlags,
5073 *(BYTE **)pvStructInfo, pcbStructInfo);
5075 else
5076 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5077 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5080 if (hFunc)
5081 CryptFreeOIDFunctionAddress(hFunc, 0);
5082 TRACE_(crypt)("returning %d\n", ret);
5083 return ret;