crypt32: Get rid of a magic number and a redundant assignment.
[wine/wine64.git] / dlls / crypt32 / decode.c
blob4ed2abe9d813f103622bf64060c8098ac06adb73
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 (!cbEncoded)
480 SetLastError(CRYPT_E_ASN1_EOD);
481 return FALSE;
483 if (pbEncoded[0] == ASN_SEQUENCE)
485 DWORD dataLen;
487 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
489 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
490 const BYTE *ptr = pbEncoded + 1 + lenBytes;
491 BOOL indefinite = FALSE;
493 cbEncoded -= 1 + lenBytes;
494 if (dataLen == CMSG_INDEFINITE_LENGTH)
496 dataLen = cbEncoded;
497 indefinite = TRUE;
499 else if (cbEncoded < dataLen)
501 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
502 cbEncoded);
503 SetLastError(CRYPT_E_ASN1_CORRUPT);
504 ret = FALSE;
506 if (ret)
508 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
509 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
510 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
512 if (cbDecoded > cbEncoded - 2)
514 /* Not enough space for 0 TLV */
515 SetLastError(CRYPT_E_ASN1_CORRUPT);
516 ret = FALSE;
518 else if (*(ptr + cbDecoded) != 0 ||
519 *(ptr + cbDecoded + 1) != 0)
521 TRACE("expected 0 TLV\n");
522 SetLastError(CRYPT_E_ASN1_CORRUPT);
523 ret = FALSE;
525 else
526 cbDecoded += 2;
529 if (ret && !indefinite && cbDecoded != dataLen)
531 TRACE("expected %d decoded, got %d, failing\n", dataLen,
532 cbDecoded);
533 SetLastError(CRYPT_E_ASN1_CORRUPT);
534 ret = FALSE;
536 if (ret)
538 DWORD i, bytesNeeded = 0, structSize = 0;
540 for (i = 0; i < cItem; i++)
542 bytesNeeded += items[i].size;
543 structSize += items[i].minSize;
545 if (pcbDecoded)
546 *pcbDecoded = 1 + lenBytes + cbDecoded;
547 if (!pvStructInfo)
548 *pcbStructInfo = bytesNeeded;
549 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
550 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
552 BYTE *nextData;
554 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
555 pvStructInfo = *(BYTE **)pvStructInfo;
556 if (startingPointer)
557 nextData = (BYTE *)startingPointer;
558 else
559 nextData = (BYTE *)pvStructInfo + structSize;
560 memset(pvStructInfo, 0, structSize);
561 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
562 ptr, dataLen, dwFlags, pvStructInfo, nextData,
563 &cbDecoded);
564 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
565 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
570 else
572 SetLastError(CRYPT_E_ASN1_BADTAG);
573 ret = FALSE;
575 TRACE("returning %d (%08x)\n", ret, GetLastError());
576 return ret;
579 /* tag:
580 * The expected tag of the entire encoded array (usually a variant
581 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
582 * regardless of the tag seen.
583 * decodeFunc:
584 * used to decode each item in the array
585 * itemSize:
586 * is the minimum size of each decoded item
587 * hasPointer:
588 * indicates whether each item has a dynamic pointer
589 * pointerOffset:
590 * indicates the offset within itemSize at which the pointer exists
592 struct AsnArrayDescriptor
594 BYTE tag;
595 InternalDecodeFunc decodeFunc;
596 DWORD itemSize;
597 BOOL hasPointer;
598 DWORD pointerOffset;
601 struct AsnArrayItemSize
603 DWORD encodedLen;
604 DWORD size;
607 /* Decodes an array of like types into a struct GenericArray.
608 * The layout and decoding of the array are described by a struct
609 * AsnArrayDescriptor.
611 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
612 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
613 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
614 DWORD *pcbDecoded, void *startingPointer)
616 BOOL ret = TRUE;
618 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
619 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
620 startingPointer);
622 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
624 DWORD dataLen;
626 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
628 DWORD bytesNeeded, cItems = 0, decoded;
629 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
630 /* There can be arbitrarily many items, but there is often only one.
632 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
634 decoded = 1 + lenBytes;
635 bytesNeeded = sizeof(struct GenericArray);
636 if (dataLen)
638 const BYTE *ptr;
639 BOOL doneDecoding = FALSE;
641 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
643 if (dataLen == CMSG_INDEFINITE_LENGTH)
645 if (ptr[0] == 0)
647 doneDecoding = TRUE;
648 if (ptr[1] != 0)
650 SetLastError(CRYPT_E_ASN1_CORRUPT);
651 ret = FALSE;
653 else
654 decoded += 2;
657 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
658 doneDecoding = TRUE;
659 if (!doneDecoding)
661 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
663 /* Each item decoded may not tolerate extraneous bytes,
664 * so get the length of the next element if known.
666 if ((ret = CRYPT_GetLengthIndefinite(ptr,
667 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
669 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
670 itemEncoded = cbEncoded - (ptr - pbEncoded);
671 else
672 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
673 itemDataLen;
675 if (ret)
676 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
677 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
678 &itemDecoded);
679 if (ret)
681 cItems++;
682 if (itemSizes != &itemSize)
683 itemSizes = CryptMemRealloc(itemSizes,
684 cItems * sizeof(struct AsnArrayItemSize));
685 else if (cItems > 1)
687 itemSizes =
688 CryptMemAlloc(
689 cItems * sizeof(struct AsnArrayItemSize));
690 if (itemSizes)
691 memcpy(itemSizes, &itemSize,
692 sizeof(itemSize));
694 if (itemSizes)
696 decoded += itemDecoded;
697 itemSizes[cItems - 1].encodedLen = itemEncoded;
698 itemSizes[cItems - 1].size = size;
699 bytesNeeded += size;
700 ptr += itemEncoded;
702 else
703 ret = FALSE;
708 if (ret)
710 if (pcbDecoded)
711 *pcbDecoded = decoded;
712 if (!pvStructInfo)
713 *pcbStructInfo = bytesNeeded;
714 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
715 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
717 DWORD i;
718 BYTE *nextData;
719 const BYTE *ptr;
720 struct GenericArray *array;
722 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
723 pvStructInfo = *(BYTE **)pvStructInfo;
724 array = (struct GenericArray *)pvStructInfo;
725 array->cItems = cItems;
726 if (startingPointer)
727 array->rgItems = startingPointer;
728 else
729 array->rgItems = (BYTE *)array +
730 sizeof(struct GenericArray);
731 nextData = array->rgItems +
732 array->cItems * arrayDesc->itemSize;
733 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
734 i < cItems && ptr - pbEncoded - 1 - lenBytes <
735 dataLen; i++)
737 DWORD itemDecoded;
739 if (arrayDesc->hasPointer)
740 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
741 + arrayDesc->pointerOffset) = nextData;
742 ret = arrayDesc->decodeFunc(ptr,
743 itemSizes[i].encodedLen,
744 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
745 array->rgItems + i * arrayDesc->itemSize,
746 &itemSizes[i].size, &itemDecoded);
747 if (ret)
749 nextData += itemSizes[i].size - arrayDesc->itemSize;
750 ptr += itemDecoded;
753 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
754 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
757 if (itemSizes != &itemSize)
758 CryptMemFree(itemSizes);
761 else
763 SetLastError(CRYPT_E_ASN1_BADTAG);
764 ret = FALSE;
766 return ret;
769 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
770 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
771 * to CRYPT_E_ASN1_CORRUPT.
772 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
773 * set!
775 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
776 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
778 BOOL ret;
779 DWORD dataLen;
781 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
783 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
784 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
786 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
787 bytesNeeded += 1 + lenBytes + dataLen;
789 if (pcbDecoded)
790 *pcbDecoded = 1 + lenBytes + dataLen;
791 if (!pvStructInfo)
792 *pcbStructInfo = bytesNeeded;
793 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
795 CRYPT_DER_BLOB *blob;
797 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
798 pvStructInfo = *(BYTE **)pvStructInfo;
799 blob = (CRYPT_DER_BLOB *)pvStructInfo;
800 blob->cbData = 1 + lenBytes + dataLen;
801 if (blob->cbData)
803 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
804 blob->pbData = (BYTE *)pbEncoded;
805 else
807 assert(blob->pbData);
808 memcpy(blob->pbData, pbEncoded, blob->cbData);
811 else
813 SetLastError(CRYPT_E_ASN1_CORRUPT);
814 ret = FALSE;
818 return ret;
821 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
822 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
823 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
824 DWORD *pcbDecoded)
826 BOOL ret;
828 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
829 pvStructInfo, *pcbStructInfo, pcbDecoded);
831 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
832 * place.
834 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
835 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
836 pcbDecoded);
837 if (ret && pvStructInfo)
839 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
841 if (blob->cbData)
843 DWORD i;
844 BYTE temp;
846 for (i = 0; i < blob->cbData / 2; i++)
848 temp = blob->pbData[i];
849 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
850 blob->pbData[blob->cbData - i - 1] = temp;
854 TRACE("returning %d (%08x)\n", ret, GetLastError());
855 return ret;
858 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
859 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
860 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
862 BOOL ret = TRUE;
864 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
865 pDecodePara, pvStructInfo, *pcbStructInfo);
867 __TRY
869 struct AsnDecodeSequenceItem items[] = {
870 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
871 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
872 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
873 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
874 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
875 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
876 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
877 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
878 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
879 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
882 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
883 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
884 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
885 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
886 pcbStructInfo, NULL, NULL);
888 __EXCEPT_PAGE_FAULT
890 SetLastError(STATUS_ACCESS_VIOLATION);
891 ret = FALSE;
893 __ENDTRY
895 TRACE("Returning %d (%08x)\n", ret, GetLastError());
896 return ret;
899 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
900 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
902 BOOL ret;
903 DWORD dataLen;
905 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
907 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
909 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
910 dwFlags, pvStructInfo, pcbStructInfo, NULL);
911 if (pcbDecoded)
912 *pcbDecoded = 1 + lenBytes + dataLen;
914 return ret;
917 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
918 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
920 BOOL ret;
922 struct AsnDecodeSequenceItem items[] = {
923 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
924 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
925 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
926 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
929 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
930 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
931 pcbDecoded, NULL);
932 return ret;
935 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
936 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
937 DWORD *pcbDecoded)
939 BOOL ret;
940 DWORD dataLen;
942 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
944 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
946 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
947 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
948 if (ret && pcbDecoded)
949 *pcbDecoded = 1 + lenBytes + dataLen;
951 return ret;
954 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
955 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
956 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
958 BOOL ret = TRUE;
959 struct AsnDecodeSequenceItem items[] = {
960 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
961 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
962 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
963 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
964 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
965 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
966 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
967 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
968 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
969 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
970 Issuer.pbData) },
971 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
972 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
973 FALSE, 0 },
974 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
975 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
976 Subject.pbData) },
977 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
978 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
979 FALSE, TRUE, offsetof(CERT_INFO,
980 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
981 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
982 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
983 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
984 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
985 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
986 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
987 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
988 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
989 offsetof(CERT_INFO, rgExtension), 0 },
992 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
993 pDecodePara, pvStructInfo, *pcbStructInfo);
995 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
996 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
997 NULL, NULL);
998 if (ret && pvStructInfo)
1000 CERT_INFO *info;
1002 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1003 info = *(CERT_INFO **)pvStructInfo;
1004 else
1005 info = (CERT_INFO *)pvStructInfo;
1006 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1007 !info->Subject.cbData)
1009 SetLastError(CRYPT_E_ASN1_CORRUPT);
1010 /* Don't need to deallocate, because it should have failed on the
1011 * first pass (and no memory was allocated.)
1013 ret = FALSE;
1017 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1018 return ret;
1021 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1022 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1023 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1025 BOOL ret = FALSE;
1027 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1028 pDecodePara, pvStructInfo, *pcbStructInfo);
1030 __TRY
1032 DWORD size = 0;
1034 /* Unless told not to, first try to decode it as a signed cert. */
1035 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1037 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1039 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1040 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1041 (BYTE *)&signedCert, &size);
1042 if (ret)
1044 size = 0;
1045 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1046 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1047 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1048 pvStructInfo, pcbStructInfo);
1049 LocalFree(signedCert);
1052 /* Failing that, try it as an unsigned cert */
1053 if (!ret)
1055 size = 0;
1056 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1057 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1058 pDecodePara, pvStructInfo, pcbStructInfo);
1061 __EXCEPT_PAGE_FAULT
1063 SetLastError(STATUS_ACCESS_VIOLATION);
1065 __ENDTRY
1067 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1068 return ret;
1071 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1072 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1074 BOOL ret;
1075 struct AsnDecodeSequenceItem items[] = {
1076 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1077 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1078 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1079 { 0, offsetof(CRL_ENTRY, RevocationDate),
1080 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1081 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1082 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1083 offsetof(CRL_ENTRY, rgExtension), 0 },
1085 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1087 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1088 *pcbStructInfo);
1090 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1091 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1092 entry ? entry->SerialNumber.pbData : NULL);
1093 if (ret && entry && !entry->SerialNumber.cbData)
1095 WARN("empty CRL entry serial number\n");
1096 SetLastError(CRYPT_E_ASN1_CORRUPT);
1097 ret = FALSE;
1099 return ret;
1102 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1103 * been set prior to calling.
1105 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1106 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1108 BOOL ret;
1109 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1110 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1111 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1112 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1114 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1115 pvStructInfo, *pcbStructInfo, pcbDecoded);
1117 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1118 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1119 entries ? entries->rgItems : NULL);
1120 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1121 return ret;
1124 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1125 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1126 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1128 struct AsnDecodeSequenceItem items[] = {
1129 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1130 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1131 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1132 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1133 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1134 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1135 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1136 Issuer.pbData) },
1137 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1138 sizeof(FILETIME), FALSE, FALSE, 0 },
1139 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1140 sizeof(FILETIME), TRUE, FALSE, 0 },
1141 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1142 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1143 offsetof(CRL_INFO, rgCRLEntry), 0 },
1144 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1145 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1146 offsetof(CRL_INFO, rgExtension), 0 },
1148 BOOL ret = TRUE;
1150 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1151 pDecodePara, pvStructInfo, *pcbStructInfo);
1153 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1154 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1155 NULL, NULL);
1157 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1158 return ret;
1161 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1162 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1163 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1165 BOOL ret = FALSE;
1167 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1168 pDecodePara, pvStructInfo, *pcbStructInfo);
1170 __TRY
1172 DWORD size = 0;
1174 /* Unless told not to, first try to decode it as a signed crl. */
1175 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1177 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1179 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1180 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1181 (BYTE *)&signedCrl, &size);
1182 if (ret)
1184 size = 0;
1185 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1186 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1187 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1188 pvStructInfo, pcbStructInfo);
1189 LocalFree(signedCrl);
1192 /* Failing that, try it as an unsigned crl */
1193 if (!ret)
1195 size = 0;
1196 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1197 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1198 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1201 __EXCEPT_PAGE_FAULT
1203 SetLastError(STATUS_ACCESS_VIOLATION);
1205 __ENDTRY
1207 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1208 return ret;
1211 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1212 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1214 BOOL ret = TRUE;
1215 DWORD dataLen;
1217 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1218 pvStructInfo, *pcbStructInfo);
1220 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1222 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1223 DWORD bytesNeeded = sizeof(LPSTR);
1225 if (dataLen)
1227 /* The largest possible string for the first two components
1228 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1230 char firstTwo[6];
1231 const BYTE *ptr;
1233 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1234 pbEncoded[1 + lenBytes] / 40,
1235 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1236 * 40);
1237 bytesNeeded += strlen(firstTwo) + 1;
1238 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1239 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1241 /* large enough for ".4000000" */
1242 char str[9];
1243 int val = 0;
1245 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1246 (*ptr & 0x80))
1248 val <<= 7;
1249 val |= *ptr & 0x7f;
1250 ptr++;
1252 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1253 (*ptr & 0x80))
1255 SetLastError(CRYPT_E_ASN1_CORRUPT);
1256 ret = FALSE;
1258 else
1260 val <<= 7;
1261 val |= *ptr++;
1262 snprintf(str, sizeof(str), ".%d", val);
1263 bytesNeeded += strlen(str);
1267 if (pcbDecoded)
1268 *pcbDecoded = 1 + lenBytes + dataLen;
1269 if (!pvStructInfo)
1270 *pcbStructInfo = bytesNeeded;
1271 else if (*pcbStructInfo < bytesNeeded)
1273 *pcbStructInfo = bytesNeeded;
1274 SetLastError(ERROR_MORE_DATA);
1275 ret = FALSE;
1277 else
1279 if (dataLen)
1281 const BYTE *ptr;
1282 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1284 *pszObjId = 0;
1285 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1286 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1287 40) * 40);
1288 pszObjId += strlen(pszObjId);
1289 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1290 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1292 int val = 0;
1294 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1295 (*ptr & 0x80))
1297 val <<= 7;
1298 val |= *ptr & 0x7f;
1299 ptr++;
1301 val <<= 7;
1302 val |= *ptr++;
1303 sprintf(pszObjId, ".%d", val);
1304 pszObjId += strlen(pszObjId);
1307 else
1308 *(LPSTR *)pvStructInfo = NULL;
1309 *pcbStructInfo = bytesNeeded;
1312 return ret;
1315 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1316 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1318 BOOL ret;
1320 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1321 pvStructInfo, *pcbStructInfo);
1323 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1324 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1325 pvStructInfo, pcbStructInfo, pcbDecoded);
1326 else
1328 SetLastError(CRYPT_E_ASN1_BADTAG);
1329 ret = FALSE;
1331 return ret;
1334 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1335 * ahead of time!
1337 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1338 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1340 struct AsnDecodeSequenceItem items[] = {
1341 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1342 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1343 offsetof(CERT_EXTENSION, pszObjId), 0 },
1344 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1345 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1346 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1347 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1348 offsetof(CERT_EXTENSION, Value.pbData) },
1350 BOOL ret = TRUE;
1351 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1353 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1354 *pcbStructInfo);
1356 if (ext)
1357 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1358 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1359 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1360 pcbDecoded, ext ? ext->pszObjId : NULL);
1361 if (ext)
1362 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1363 debugstr_a(ext->pszObjId));
1364 TRACE("returning %d (%08x)\n", ret, GetLastError());
1365 return ret;
1368 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1369 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1370 DWORD *pcbDecoded)
1372 BOOL ret = TRUE;
1373 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1374 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1375 offsetof(CERT_EXTENSION, pszObjId) };
1376 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1378 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1379 pvStructInfo, *pcbStructInfo, pcbDecoded);
1381 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1382 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1383 exts ? exts->rgExtension : NULL);
1384 return ret;
1387 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1388 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1389 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1391 BOOL ret = TRUE;
1393 __TRY
1395 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1396 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1397 if (ret && pvStructInfo)
1399 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1400 pcbStructInfo, *pcbStructInfo);
1401 if (ret)
1403 CERT_EXTENSIONS *exts;
1405 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1406 pvStructInfo = *(BYTE **)pvStructInfo;
1407 exts = (CERT_EXTENSIONS *)pvStructInfo;
1408 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1409 sizeof(CERT_EXTENSIONS));
1410 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1411 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1412 pcbStructInfo, NULL);
1416 __EXCEPT_PAGE_FAULT
1418 SetLastError(STATUS_ACCESS_VIOLATION);
1419 ret = FALSE;
1421 __ENDTRY
1422 return ret;
1425 /* Warning: this assumes the address of value->Value.pbData is already set, in
1426 * order to avoid overwriting memory. (In some cases, it may change it, if it
1427 * doesn't copy anything to memory.) Be sure to set it correctly!
1429 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1430 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1431 DWORD *pcbDecoded)
1433 BOOL ret = TRUE;
1434 DWORD dataLen;
1435 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1437 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1439 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1440 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1442 switch (pbEncoded[0])
1444 case ASN_OCTETSTRING:
1445 valueType = CERT_RDN_OCTET_STRING;
1446 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1447 bytesNeeded += dataLen;
1448 break;
1449 case ASN_NUMERICSTRING:
1450 valueType = CERT_RDN_NUMERIC_STRING;
1451 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1452 bytesNeeded += dataLen;
1453 break;
1454 case ASN_PRINTABLESTRING:
1455 valueType = CERT_RDN_PRINTABLE_STRING;
1456 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1457 bytesNeeded += dataLen;
1458 break;
1459 case ASN_IA5STRING:
1460 valueType = CERT_RDN_IA5_STRING;
1461 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1462 bytesNeeded += dataLen;
1463 break;
1464 case ASN_T61STRING:
1465 valueType = CERT_RDN_T61_STRING;
1466 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1467 bytesNeeded += dataLen;
1468 break;
1469 case ASN_VIDEOTEXSTRING:
1470 valueType = CERT_RDN_VIDEOTEX_STRING;
1471 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1472 bytesNeeded += dataLen;
1473 break;
1474 case ASN_GRAPHICSTRING:
1475 valueType = CERT_RDN_GRAPHIC_STRING;
1476 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1477 bytesNeeded += dataLen;
1478 break;
1479 case ASN_VISIBLESTRING:
1480 valueType = CERT_RDN_VISIBLE_STRING;
1481 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1482 bytesNeeded += dataLen;
1483 break;
1484 case ASN_GENERALSTRING:
1485 valueType = CERT_RDN_GENERAL_STRING;
1486 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1487 bytesNeeded += dataLen;
1488 break;
1489 case ASN_UNIVERSALSTRING:
1490 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1491 SetLastError(CRYPT_E_ASN1_BADTAG);
1492 return FALSE;
1493 case ASN_BMPSTRING:
1494 valueType = CERT_RDN_BMP_STRING;
1495 bytesNeeded += dataLen;
1496 break;
1497 case ASN_UTF8STRING:
1498 valueType = CERT_RDN_UTF8_STRING;
1499 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1500 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1501 break;
1502 default:
1503 SetLastError(CRYPT_E_ASN1_BADTAG);
1504 return FALSE;
1507 if (pcbDecoded)
1508 *pcbDecoded = 1 + lenBytes + dataLen;
1509 if (!value)
1510 *pcbStructInfo = bytesNeeded;
1511 else if (*pcbStructInfo < bytesNeeded)
1513 *pcbStructInfo = bytesNeeded;
1514 SetLastError(ERROR_MORE_DATA);
1515 ret = FALSE;
1517 else
1519 *pcbStructInfo = bytesNeeded;
1520 value->dwValueType = valueType;
1521 if (dataLen)
1523 DWORD i;
1525 assert(value->Value.pbData);
1526 switch (pbEncoded[0])
1528 case ASN_OCTETSTRING:
1529 case ASN_NUMERICSTRING:
1530 case ASN_PRINTABLESTRING:
1531 case ASN_IA5STRING:
1532 case ASN_T61STRING:
1533 case ASN_VIDEOTEXSTRING:
1534 case ASN_GRAPHICSTRING:
1535 case ASN_VISIBLESTRING:
1536 case ASN_GENERALSTRING:
1537 value->Value.cbData = dataLen;
1538 if (dataLen)
1540 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1541 memcpy(value->Value.pbData,
1542 pbEncoded + 1 + lenBytes, dataLen);
1543 else
1544 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1545 lenBytes;
1547 break;
1548 case ASN_BMPSTRING:
1550 LPWSTR str = (LPWSTR)value->Value.pbData;
1552 value->Value.cbData = dataLen;
1553 for (i = 0; i < dataLen / 2; i++)
1554 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1555 pbEncoded[1 + lenBytes + 2 * i + 1];
1556 break;
1558 case ASN_UTF8STRING:
1560 LPWSTR str = (LPWSTR)value->Value.pbData;
1562 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1563 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1564 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1565 break;
1569 else
1571 value->Value.cbData = 0;
1572 value->Value.pbData = NULL;
1576 return ret;
1579 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1580 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1581 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1583 BOOL ret = TRUE;
1585 __TRY
1587 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1588 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1589 if (ret && pvStructInfo)
1591 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1592 pcbStructInfo, *pcbStructInfo);
1593 if (ret)
1595 CERT_NAME_VALUE *value;
1597 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1598 pvStructInfo = *(BYTE **)pvStructInfo;
1599 value = (CERT_NAME_VALUE *)pvStructInfo;
1600 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1601 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1602 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1603 pcbStructInfo, NULL);
1607 __EXCEPT_PAGE_FAULT
1609 SetLastError(STATUS_ACCESS_VIOLATION);
1610 ret = FALSE;
1612 __ENDTRY
1613 return ret;
1616 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1617 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1618 DWORD *pcbDecoded)
1620 BOOL ret = TRUE;
1621 DWORD dataLen;
1622 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1624 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1626 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1627 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1629 switch (pbEncoded[0])
1631 case ASN_NUMERICSTRING:
1632 valueType = CERT_RDN_NUMERIC_STRING;
1633 bytesNeeded += dataLen * 2;
1634 break;
1635 case ASN_PRINTABLESTRING:
1636 valueType = CERT_RDN_PRINTABLE_STRING;
1637 bytesNeeded += dataLen * 2;
1638 break;
1639 case ASN_IA5STRING:
1640 valueType = CERT_RDN_IA5_STRING;
1641 bytesNeeded += dataLen * 2;
1642 break;
1643 case ASN_T61STRING:
1644 valueType = CERT_RDN_T61_STRING;
1645 bytesNeeded += dataLen * 2;
1646 break;
1647 case ASN_VIDEOTEXSTRING:
1648 valueType = CERT_RDN_VIDEOTEX_STRING;
1649 bytesNeeded += dataLen * 2;
1650 break;
1651 case ASN_GRAPHICSTRING:
1652 valueType = CERT_RDN_GRAPHIC_STRING;
1653 bytesNeeded += dataLen * 2;
1654 break;
1655 case ASN_VISIBLESTRING:
1656 valueType = CERT_RDN_VISIBLE_STRING;
1657 bytesNeeded += dataLen * 2;
1658 break;
1659 case ASN_GENERALSTRING:
1660 valueType = CERT_RDN_GENERAL_STRING;
1661 bytesNeeded += dataLen * 2;
1662 break;
1663 case ASN_UNIVERSALSTRING:
1664 valueType = CERT_RDN_UNIVERSAL_STRING;
1665 bytesNeeded += dataLen / 2;
1666 break;
1667 case ASN_BMPSTRING:
1668 valueType = CERT_RDN_BMP_STRING;
1669 bytesNeeded += dataLen;
1670 break;
1671 case ASN_UTF8STRING:
1672 valueType = CERT_RDN_UTF8_STRING;
1673 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1674 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1675 break;
1676 default:
1677 SetLastError(CRYPT_E_ASN1_BADTAG);
1678 return FALSE;
1681 if (pcbDecoded)
1682 *pcbDecoded = 1 + lenBytes + dataLen;
1683 if (!value)
1684 *pcbStructInfo = bytesNeeded;
1685 else if (*pcbStructInfo < bytesNeeded)
1687 *pcbStructInfo = bytesNeeded;
1688 SetLastError(ERROR_MORE_DATA);
1689 ret = FALSE;
1691 else
1693 *pcbStructInfo = bytesNeeded;
1694 value->dwValueType = valueType;
1695 if (dataLen)
1697 DWORD i;
1698 LPWSTR str = (LPWSTR)value->Value.pbData;
1700 assert(value->Value.pbData);
1701 switch (pbEncoded[0])
1703 case ASN_NUMERICSTRING:
1704 case ASN_PRINTABLESTRING:
1705 case ASN_IA5STRING:
1706 case ASN_T61STRING:
1707 case ASN_VIDEOTEXSTRING:
1708 case ASN_GRAPHICSTRING:
1709 case ASN_VISIBLESTRING:
1710 case ASN_GENERALSTRING:
1711 value->Value.cbData = dataLen * 2;
1712 for (i = 0; i < dataLen; i++)
1713 str[i] = pbEncoded[1 + lenBytes + i];
1714 break;
1715 case ASN_UNIVERSALSTRING:
1716 value->Value.cbData = dataLen / 2;
1717 for (i = 0; i < dataLen / 4; i++)
1718 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1719 | pbEncoded[1 + lenBytes + 2 * i + 3];
1720 break;
1721 case ASN_BMPSTRING:
1722 value->Value.cbData = dataLen;
1723 for (i = 0; i < dataLen / 2; i++)
1724 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1725 pbEncoded[1 + lenBytes + 2 * i + 1];
1726 break;
1727 case ASN_UTF8STRING:
1728 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1729 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1730 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1731 break;
1734 else
1736 value->Value.cbData = 0;
1737 value->Value.pbData = NULL;
1741 return ret;
1744 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1745 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1746 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1748 BOOL ret = TRUE;
1750 __TRY
1752 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1753 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1754 if (ret && pvStructInfo)
1756 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1757 pcbStructInfo, *pcbStructInfo);
1758 if (ret)
1760 CERT_NAME_VALUE *value;
1762 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1763 pvStructInfo = *(BYTE **)pvStructInfo;
1764 value = (CERT_NAME_VALUE *)pvStructInfo;
1765 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1766 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1767 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1768 pcbStructInfo, NULL);
1772 __EXCEPT_PAGE_FAULT
1774 SetLastError(STATUS_ACCESS_VIOLATION);
1775 ret = FALSE;
1777 __ENDTRY
1778 return ret;
1781 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1782 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1784 BOOL ret;
1785 struct AsnDecodeSequenceItem items[] = {
1786 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1787 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1788 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1789 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1790 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1791 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1793 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1795 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1796 pvStructInfo, *pcbStructInfo);
1798 if (attr)
1799 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1800 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1801 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1802 attr ? attr->pszObjId : NULL);
1803 if (attr)
1805 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1806 debugstr_a(attr->pszObjId));
1807 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1809 TRACE("returning %d (%08x)\n", ret, GetLastError());
1810 return ret;
1813 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1814 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1816 BOOL ret = TRUE;
1817 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1818 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1819 offsetof(CERT_RDN_ATTR, pszObjId) };
1820 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1822 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1823 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1824 rdn ? rdn->rgRDNAttr : NULL);
1825 return ret;
1828 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1829 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1830 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1832 BOOL ret = TRUE;
1834 __TRY
1836 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1837 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1838 offsetof(CERT_RDN, rgRDNAttr) };
1840 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1841 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1843 __EXCEPT_PAGE_FAULT
1845 SetLastError(STATUS_ACCESS_VIOLATION);
1846 ret = FALSE;
1848 __ENDTRY
1849 return ret;
1852 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1853 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1854 DWORD *pcbDecoded)
1856 BOOL ret;
1857 struct AsnDecodeSequenceItem items[] = {
1858 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1859 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1860 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1861 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1862 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1863 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1865 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1867 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1868 pvStructInfo, *pcbStructInfo);
1870 if (attr)
1871 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1872 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1873 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1874 attr ? attr->pszObjId : NULL);
1875 if (attr)
1877 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1878 debugstr_a(attr->pszObjId));
1879 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1881 TRACE("returning %d (%08x)\n", ret, GetLastError());
1882 return ret;
1885 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1886 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1888 BOOL ret = TRUE;
1889 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1890 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1891 offsetof(CERT_RDN_ATTR, pszObjId) };
1892 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1894 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1895 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1896 rdn ? rdn->rgRDNAttr : NULL);
1897 return ret;
1900 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1901 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1902 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1904 BOOL ret = TRUE;
1906 __TRY
1908 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1909 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1910 offsetof(CERT_RDN, rgRDNAttr) };
1912 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1913 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1915 __EXCEPT_PAGE_FAULT
1917 SetLastError(STATUS_ACCESS_VIOLATION);
1918 ret = FALSE;
1920 __ENDTRY
1921 return ret;
1924 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1925 DWORD *pcbDecoded)
1927 BOOL ret = TRUE, done = FALSE;
1928 DWORD indefiniteNestingLevels = 0, decoded = 0;
1930 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1932 do {
1933 DWORD dataLen;
1935 if (!cbEncoded)
1936 done = TRUE;
1937 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
1938 &dataLen)))
1940 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1942 if (dataLen == CMSG_INDEFINITE_LENGTH)
1944 indefiniteNestingLevels++;
1945 pbEncoded += 1 + lenBytes;
1946 cbEncoded -= 1 + lenBytes;
1947 decoded += 1 + lenBytes;
1948 TRACE("indefiniteNestingLevels = %d\n",
1949 indefiniteNestingLevels);
1951 else
1953 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
1954 indefiniteNestingLevels)
1956 indefiniteNestingLevels--;
1957 TRACE("indefiniteNestingLevels = %d\n",
1958 indefiniteNestingLevels);
1960 pbEncoded += 1 + lenBytes + dataLen;
1961 cbEncoded -= 1 + lenBytes + dataLen;
1962 decoded += 1 + lenBytes + dataLen;
1963 if (!indefiniteNestingLevels)
1964 done = TRUE;
1967 } while (ret && !done);
1968 /* If we haven't found all 0 TLVs, we haven't found the end */
1969 if (ret && indefiniteNestingLevels)
1971 SetLastError(CRYPT_E_ASN1_EOD);
1972 ret = FALSE;
1974 if (ret)
1975 *pcbDecoded = decoded;
1976 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
1977 return ret;
1980 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1981 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1982 DWORD *pcbDecoded)
1984 BOOL ret = TRUE;
1985 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
1987 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1988 pvStructInfo, *pcbStructInfo);
1990 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
1992 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1993 bytesNeeded += encodedLen;
1994 if (!pvStructInfo)
1995 *pcbStructInfo = bytesNeeded;
1996 else if (*pcbStructInfo < bytesNeeded)
1998 SetLastError(ERROR_MORE_DATA);
1999 *pcbStructInfo = bytesNeeded;
2000 ret = FALSE;
2002 else
2004 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
2006 *pcbStructInfo = bytesNeeded;
2007 blob->cbData = encodedLen;
2008 if (encodedLen)
2010 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2011 blob->pbData = (LPBYTE)pbEncoded;
2012 else
2014 assert(blob->pbData);
2015 memcpy(blob->pbData, pbEncoded, blob->cbData);
2018 else
2019 blob->pbData = NULL;
2021 if (pcbDecoded)
2022 *pcbDecoded = encodedLen;
2024 return ret;
2027 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
2028 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2030 BOOL ret;
2031 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
2032 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2033 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
2035 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2036 pvStructInfo, *pcbStructInfo, pcbDecoded);
2038 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2039 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2040 array ? array->rgItems : NULL);
2041 return ret;
2044 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2045 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2047 BOOL ret;
2048 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2049 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2050 CTL_USAGE *usage = (CTL_USAGE *)pvStructInfo;
2052 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2053 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2054 usage ? usage->rgpszUsageIdentifier : NULL);
2055 return ret;
2058 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2059 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2061 struct AsnDecodeSequenceItem items[] = {
2062 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2063 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2064 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2065 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2066 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), FALSE,
2067 TRUE, offsetof(CTL_ENTRY, rgAttribute), 0 },
2069 BOOL ret = TRUE;
2070 CTL_ENTRY *entry = (CTL_ENTRY *)pvStructInfo;
2072 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2073 *pcbStructInfo);
2075 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2076 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2077 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2078 return ret;
2081 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2082 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2084 BOOL ret;
2085 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2086 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2087 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2088 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2090 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2091 pvStructInfo, *pcbStructInfo, pcbDecoded);
2093 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2094 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2095 entries ? entries->rgItems : NULL);
2096 return ret;
2099 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2100 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2101 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2103 BOOL ret = FALSE;
2105 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2106 pDecodePara, pvStructInfo, *pcbStructInfo);
2108 __TRY
2110 struct AsnDecodeSequenceItem items[] = {
2111 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2112 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2113 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2114 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2115 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2116 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2117 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
2118 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2119 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2120 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2121 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2122 { 0, offsetof(CTL_INFO, ThisUpdate),
2123 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2124 0 },
2125 { 0, offsetof(CTL_INFO, NextUpdate),
2126 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2127 0 },
2128 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2129 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2130 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2131 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2132 CRYPT_AsnDecodeCTLEntries, sizeof(struct GenericArray),
2133 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2134 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2135 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
2136 offsetof(CTL_INFO, rgExtension), 0 },
2139 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2140 pDecodePara, pvStructInfo, *pcbStructInfo);
2142 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2143 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2144 pcbStructInfo, NULL, NULL);
2146 __EXCEPT_PAGE_FAULT
2148 SetLastError(STATUS_ACCESS_VIOLATION);
2150 __ENDTRY
2151 return ret;
2154 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2155 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2156 DWORD *pcbDecoded)
2158 BOOL ret;
2159 struct AsnDecodeSequenceItem items[] = {
2160 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2161 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2162 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2163 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2164 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2165 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2167 PCRYPT_SMIME_CAPABILITY capability = (PCRYPT_SMIME_CAPABILITY)pvStructInfo;
2169 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2170 pvStructInfo, *pcbStructInfo);
2172 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2173 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2174 pcbDecoded, capability ? capability->pszObjId : NULL);
2175 TRACE("returning %d\n", ret);
2176 return ret;
2179 static BOOL CRYPT_AsnDecodeSMIMECapabilitiesInternal(const BYTE *pbEncoded,
2180 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2181 DWORD *pcbDecoded)
2183 struct AsnArrayDescriptor arrayDesc = { 0,
2184 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2185 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2186 PCRYPT_SMIME_CAPABILITIES capabilities =
2187 (PCRYPT_SMIME_CAPABILITIES)pvStructInfo;
2188 BOOL ret;
2190 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2191 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2192 capabilities ? capabilities->rgCapability : NULL);
2193 return ret;
2196 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2197 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2198 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2200 BOOL ret = FALSE;
2202 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2203 pDecodePara, pvStructInfo, *pcbStructInfo);
2205 __TRY
2207 DWORD bytesNeeded;
2209 if (!cbEncoded)
2210 SetLastError(CRYPT_E_ASN1_EOD);
2211 else if (pbEncoded[0] != ASN_SEQUENCEOF)
2212 SetLastError(CRYPT_E_ASN1_CORRUPT);
2213 else if ((ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
2214 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2215 NULL)))
2217 if (!pvStructInfo)
2218 *pcbStructInfo = bytesNeeded;
2219 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2220 pvStructInfo, pcbStructInfo, bytesNeeded)))
2222 PCRYPT_SMIME_CAPABILITIES capabilities;
2224 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2225 pvStructInfo = *(BYTE **)pvStructInfo;
2226 capabilities = (PCRYPT_SMIME_CAPABILITIES)pvStructInfo;
2227 capabilities->rgCapability =
2228 (PCRYPT_SMIME_CAPABILITY)((BYTE *)pvStructInfo +
2229 sizeof(CRYPT_SMIME_CAPABILITIES));
2230 ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
2231 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2232 &bytesNeeded, NULL);
2236 __EXCEPT_PAGE_FAULT
2238 SetLastError(STATUS_ACCESS_VIOLATION);
2240 __ENDTRY
2241 TRACE("returning %d\n", ret);
2242 return ret;
2245 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2246 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2247 DWORD *pcbDecoded)
2249 BOOL ret;
2250 struct AsnDecodeSequenceItem items[] = {
2251 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2252 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2253 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2254 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2255 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
2256 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2258 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2260 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2261 pvStructInfo, *pcbStructInfo);
2263 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2264 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2265 pcbDecoded, attr ? attr->pszObjId : NULL);
2266 TRACE("returning %d\n", ret);
2267 return ret;
2270 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2271 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2272 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2274 BOOL ret = FALSE;
2276 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2277 pDecodePara, pvStructInfo, *pcbStructInfo);
2279 __TRY
2281 DWORD bytesNeeded;
2283 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2284 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2285 if (ret)
2287 if (!pvStructInfo)
2288 *pcbStructInfo = bytesNeeded;
2289 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2290 pvStructInfo, pcbStructInfo, bytesNeeded)))
2292 PCRYPT_ATTRIBUTE attr;
2294 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2295 pvStructInfo = *(BYTE **)pvStructInfo;
2296 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2297 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2298 sizeof(CRYPT_ATTRIBUTE));
2299 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2300 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2301 NULL);
2305 __EXCEPT_PAGE_FAULT
2307 SetLastError(STATUS_ACCESS_VIOLATION);
2309 __ENDTRY
2310 TRACE("returning %d\n", ret);
2311 return ret;
2314 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2315 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2316 DWORD *pcbDecoded)
2318 struct AsnArrayDescriptor arrayDesc = { 0,
2319 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2320 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2321 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2322 BOOL ret;
2324 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2325 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2326 NULL);
2327 return ret;
2330 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2331 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2332 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2334 BOOL ret = FALSE;
2336 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2337 pDecodePara, pvStructInfo, *pcbStructInfo);
2339 __TRY
2341 DWORD bytesNeeded;
2343 if (!cbEncoded)
2344 SetLastError(CRYPT_E_ASN1_EOD);
2345 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2346 SetLastError(CRYPT_E_ASN1_CORRUPT);
2347 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2348 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2349 NULL)))
2351 if (!pvStructInfo)
2352 *pcbStructInfo = bytesNeeded;
2353 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2354 pvStructInfo, pcbStructInfo, bytesNeeded)))
2356 PCRYPT_ATTRIBUTES attrs;
2358 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2359 pvStructInfo = *(BYTE **)pvStructInfo;
2360 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2361 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2362 sizeof(CRYPT_ATTRIBUTES));
2363 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2364 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2365 &bytesNeeded, NULL);
2369 __EXCEPT_PAGE_FAULT
2371 SetLastError(STATUS_ACCESS_VIOLATION);
2373 __ENDTRY
2374 TRACE("returning %d\n", ret);
2375 return ret;
2378 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2379 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2381 CRYPT_ALGORITHM_IDENTIFIER *algo =
2382 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2383 BOOL ret = TRUE;
2384 struct AsnDecodeSequenceItem items[] = {
2385 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2386 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2387 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2388 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2389 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2390 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2393 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2394 pvStructInfo, *pcbStructInfo, pcbDecoded);
2396 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2397 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2398 pcbDecoded, algo ? algo->pszObjId : NULL);
2399 if (ret && pvStructInfo)
2401 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2402 debugstr_a(algo->pszObjId));
2404 return ret;
2407 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2408 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2409 DWORD *pcbDecoded)
2411 BOOL ret = TRUE;
2412 struct AsnDecodeSequenceItem items[] = {
2413 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2414 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2415 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2416 Algorithm.pszObjId) },
2417 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2418 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2419 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2421 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2423 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2424 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2425 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2426 return ret;
2429 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2430 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2431 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2433 BOOL ret = TRUE;
2435 __TRY
2437 DWORD bytesNeeded;
2439 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2440 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2442 if (!pvStructInfo)
2443 *pcbStructInfo = bytesNeeded;
2444 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2445 pvStructInfo, pcbStructInfo, bytesNeeded)))
2447 PCERT_PUBLIC_KEY_INFO info;
2449 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2450 pvStructInfo = *(BYTE **)pvStructInfo;
2451 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2452 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2453 sizeof(CERT_PUBLIC_KEY_INFO);
2454 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2455 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2456 &bytesNeeded, NULL);
2460 __EXCEPT_PAGE_FAULT
2462 SetLastError(STATUS_ACCESS_VIOLATION);
2463 ret = FALSE;
2465 __ENDTRY
2466 return ret;
2469 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2470 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2472 BOOL ret;
2474 if (cbEncoded < 3)
2476 SetLastError(CRYPT_E_ASN1_CORRUPT);
2477 return FALSE;
2479 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2481 SetLastError(CRYPT_E_ASN1_CORRUPT);
2482 return FALSE;
2484 if (pbEncoded[1] > 1)
2486 SetLastError(CRYPT_E_ASN1_CORRUPT);
2487 return FALSE;
2489 if (pcbDecoded)
2490 *pcbDecoded = 3;
2491 if (!pvStructInfo)
2493 *pcbStructInfo = sizeof(BOOL);
2494 ret = TRUE;
2496 else if (*pcbStructInfo < sizeof(BOOL))
2498 *pcbStructInfo = sizeof(BOOL);
2499 SetLastError(ERROR_MORE_DATA);
2500 ret = FALSE;
2502 else
2504 *pcbStructInfo = sizeof(BOOL);
2505 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2506 ret = TRUE;
2508 TRACE("returning %d (%08x)\n", ret, GetLastError());
2509 return ret;
2512 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2513 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2515 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2516 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2517 BOOL ret;
2519 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2520 pvStructInfo, *pcbStructInfo);
2522 if (cbEncoded < 2)
2524 SetLastError(CRYPT_E_ASN1_CORRUPT);
2525 return FALSE;
2527 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2528 if (1 + lenBytes > cbEncoded)
2530 SetLastError(CRYPT_E_ASN1_CORRUPT);
2531 return FALSE;
2533 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2535 switch (pbEncoded[0] & ASN_TYPE_MASK)
2537 case 1: /* rfc822Name */
2538 case 2: /* dNSName */
2539 case 6: /* uniformResourceIdentifier */
2540 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2541 break;
2542 case 4: /* directoryName */
2543 case 7: /* iPAddress */
2544 bytesNeeded += dataLen;
2545 break;
2546 case 8: /* registeredID */
2547 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2548 &dataLen, NULL);
2549 if (ret)
2551 /* FIXME: ugly, shouldn't need to know internals of OID decode
2552 * function to use it.
2554 bytesNeeded += dataLen - sizeof(LPSTR);
2556 break;
2557 case 0: /* otherName */
2558 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2559 SetLastError(CRYPT_E_ASN1_BADTAG);
2560 ret = FALSE;
2561 break;
2562 case 3: /* x400Address, unimplemented */
2563 case 5: /* ediPartyName, unimplemented */
2564 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2565 SetLastError(CRYPT_E_ASN1_BADTAG);
2566 ret = FALSE;
2567 break;
2568 default:
2569 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2570 SetLastError(CRYPT_E_ASN1_CORRUPT);
2571 ret = FALSE;
2573 if (ret)
2575 if (pcbDecoded)
2576 *pcbDecoded = 1 + lenBytes + dataLen;
2577 if (!entry)
2578 *pcbStructInfo = bytesNeeded;
2579 else if (*pcbStructInfo < bytesNeeded)
2581 *pcbStructInfo = bytesNeeded;
2582 SetLastError(ERROR_MORE_DATA);
2583 ret = FALSE;
2585 else
2587 *pcbStructInfo = bytesNeeded;
2588 /* MS used values one greater than the asn1 ones.. sigh */
2589 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
2590 switch (pbEncoded[0] & ASN_TYPE_MASK)
2592 case 1: /* rfc822Name */
2593 case 2: /* dNSName */
2594 case 6: /* uniformResourceIdentifier */
2596 DWORD i;
2598 for (i = 0; i < dataLen; i++)
2599 entry->u.pwszURL[i] =
2600 (WCHAR)pbEncoded[1 + lenBytes + i];
2601 entry->u.pwszURL[i] = 0;
2602 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2603 debugstr_w(entry->u.pwszURL));
2604 break;
2606 case 4: /* directoryName */
2607 /* The data are memory-equivalent with the IPAddress case,
2608 * fall-through
2610 case 7: /* iPAddress */
2611 /* The next data pointer is in the pwszURL spot, that is,
2612 * the first 4 bytes. Need to move it to the next spot.
2614 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2615 entry->u.IPAddress.cbData = dataLen;
2616 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2617 dataLen);
2618 break;
2619 case 8: /* registeredID */
2620 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2621 &entry->u.pszRegisteredID, &dataLen, NULL);
2622 break;
2627 return ret;
2630 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2631 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2632 DWORD *pcbDecoded)
2634 BOOL ret = TRUE;
2635 struct AsnArrayDescriptor arrayDesc = { 0,
2636 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2637 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2638 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2640 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2641 pvStructInfo, *pcbStructInfo, pcbDecoded);
2643 if (info)
2644 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2645 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2646 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2647 info ? info->rgAltEntry : NULL);
2648 return ret;
2651 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2652 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2653 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2654 DWORD *pcbDecoded)
2656 BOOL ret;
2658 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2659 pvStructInfo, *pcbStructInfo, pcbDecoded);
2661 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2662 * place.
2664 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2665 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2666 pcbDecoded);
2667 if (ret && pvStructInfo)
2669 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2671 if (blob->cbData)
2673 DWORD i;
2674 BYTE temp;
2676 for (i = 0; i < blob->cbData / 2; i++)
2678 temp = blob->pbData[i];
2679 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2680 blob->pbData[blob->cbData - i - 1] = temp;
2684 TRACE("returning %d (%08x)\n", ret, GetLastError());
2685 return ret;
2688 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2689 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2690 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2692 BOOL ret;
2694 __TRY
2696 struct AsnDecodeSequenceItem items[] = {
2697 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2698 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2699 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2700 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2701 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2702 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2703 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2704 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2705 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2706 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2707 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2710 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2711 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2712 pcbStructInfo, NULL, NULL);
2714 __EXCEPT_PAGE_FAULT
2716 SetLastError(STATUS_ACCESS_VIOLATION);
2717 ret = FALSE;
2719 __ENDTRY
2720 return ret;
2723 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2724 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2725 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2727 BOOL ret;
2729 __TRY
2731 struct AsnDecodeSequenceItem items[] = {
2732 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2733 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2734 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2735 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2736 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2737 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2738 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2739 AuthorityCertIssuer.rgAltEntry), 0 },
2740 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2741 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2742 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2743 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2744 AuthorityCertSerialNumber.pbData), 0 },
2747 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2748 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2749 pcbStructInfo, NULL, NULL);
2751 __EXCEPT_PAGE_FAULT
2753 SetLastError(STATUS_ACCESS_VIOLATION);
2754 ret = FALSE;
2756 __ENDTRY
2757 return ret;
2760 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
2761 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2762 DWORD *pcbDecoded)
2764 struct AsnDecodeSequenceItem items[] = {
2765 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
2766 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
2767 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
2768 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
2769 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
2770 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
2772 CERT_ACCESS_DESCRIPTION *descr = (CERT_ACCESS_DESCRIPTION *)pvStructInfo;
2774 return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2775 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2776 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
2779 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2780 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2781 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2783 BOOL ret;
2785 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2786 pDecodePara, pvStructInfo, *pcbStructInfo);
2788 __TRY
2790 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2791 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
2792 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
2794 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2795 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2797 __EXCEPT_PAGE_FAULT
2799 SetLastError(STATUS_ACCESS_VIOLATION);
2800 ret = FALSE;
2802 __ENDTRY
2803 return ret;
2806 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
2807 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2809 BOOL ret;
2810 DWORD dataLen;
2812 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2813 pvStructInfo, *pcbStructInfo, pcbDecoded);
2815 /* The caller has already checked the tag, no need to check it again.
2816 * Check the outer length is valid:
2818 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
2820 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2821 DWORD innerLen;
2823 pbEncoded += 1 + lenBytes;
2824 cbEncoded -= 1 + lenBytes;
2825 if (dataLen == CMSG_INDEFINITE_LENGTH)
2826 cbEncoded -= 2; /* space for 0 TLV */
2827 /* Check the inner length is valid: */
2828 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
2830 DWORD decodedLen;
2832 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
2833 pvStructInfo, pcbStructInfo, &decodedLen);
2834 if (dataLen == CMSG_INDEFINITE_LENGTH)
2836 if (*(pbEncoded + decodedLen) != 0 ||
2837 *(pbEncoded + decodedLen + 1) != 0)
2839 TRACE("expected 0 TLV, got {%02x,%02x}\n",
2840 *(pbEncoded + decodedLen),
2841 *(pbEncoded + decodedLen + 1));
2842 SetLastError(CRYPT_E_ASN1_CORRUPT);
2843 ret = FALSE;
2845 else
2846 decodedLen += 2;
2848 if (ret && pcbDecoded)
2850 *pcbDecoded = 1 + lenBytes + decodedLen;
2851 TRACE("decoded %d bytes\n", *pcbDecoded);
2855 return ret;
2858 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
2859 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2860 DWORD *pcbDecoded)
2862 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2863 struct AsnDecodeSequenceItem items[] = {
2864 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2865 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2866 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2867 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2868 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2869 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2870 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2872 BOOL ret;
2874 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2875 pvStructInfo, *pcbStructInfo, pcbDecoded);
2877 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2878 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2879 pcbDecoded, info ? info->pszObjId : NULL);
2880 return ret;
2883 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2884 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2885 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2887 BOOL ret = FALSE;
2889 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2890 pDecodePara, pvStructInfo, *pcbStructInfo);
2892 __TRY
2894 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
2895 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2896 if (ret && pvStructInfo)
2898 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2899 pcbStructInfo, *pcbStructInfo);
2900 if (ret)
2902 CRYPT_CONTENT_INFO *info;
2904 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2905 pvStructInfo = *(BYTE **)pvStructInfo;
2906 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2907 info->pszObjId = (LPSTR)((BYTE *)info +
2908 sizeof(CRYPT_CONTENT_INFO));
2909 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
2910 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2911 pcbStructInfo, NULL);
2915 __EXCEPT_PAGE_FAULT
2917 SetLastError(STATUS_ACCESS_VIOLATION);
2919 __ENDTRY
2920 return ret;
2923 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2924 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2925 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2927 BOOL ret;
2928 struct AsnDecodeSequenceItem items[] = {
2929 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2930 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2931 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2932 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2933 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2934 0 },
2935 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2936 CRYPT_AsnDecodePKCSContentInfoInternal,
2937 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2938 ContentInfo.pszObjId), 0 },
2939 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2940 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2941 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2944 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2945 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
2946 NULL, NULL);
2947 return ret;
2950 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2951 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2952 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2954 BOOL ret = TRUE;
2956 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2957 pDecodePara, pvStructInfo, *pcbStructInfo);
2959 __TRY
2961 DWORD bytesNeeded;
2963 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2964 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2966 if (!pvStructInfo)
2967 *pcbStructInfo = bytesNeeded;
2968 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2969 pvStructInfo, pcbStructInfo, bytesNeeded)))
2971 CERT_ALT_NAME_INFO *name;
2973 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2974 pvStructInfo = *(BYTE **)pvStructInfo;
2975 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2976 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2977 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2978 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2979 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2980 &bytesNeeded, NULL);
2984 __EXCEPT_PAGE_FAULT
2986 SetLastError(STATUS_ACCESS_VIOLATION);
2987 ret = FALSE;
2989 __ENDTRY
2990 return ret;
2993 struct PATH_LEN_CONSTRAINT
2995 BOOL fPathLenConstraint;
2996 DWORD dwPathLenConstraint;
2999 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3000 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3001 DWORD *pcbDecoded)
3003 BOOL ret = TRUE;
3004 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3006 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3007 pvStructInfo, *pcbStructInfo, pcbDecoded);
3009 if (!pvStructInfo)
3011 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3012 &size, pcbDecoded);
3013 *pcbStructInfo = bytesNeeded;
3015 else if (*pcbStructInfo < bytesNeeded)
3017 SetLastError(ERROR_MORE_DATA);
3018 *pcbStructInfo = bytesNeeded;
3019 ret = FALSE;
3021 else
3023 struct PATH_LEN_CONSTRAINT *constraint =
3024 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
3026 *pcbStructInfo = bytesNeeded;
3027 size = sizeof(constraint->dwPathLenConstraint);
3028 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3029 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3030 if (ret)
3031 constraint->fPathLenConstraint = TRUE;
3032 TRACE("got an int, dwPathLenConstraint is %d\n",
3033 constraint->dwPathLenConstraint);
3035 TRACE("returning %d (%08x)\n", ret, GetLastError());
3036 return ret;
3039 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3040 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3041 DWORD *pcbDecoded)
3043 BOOL ret;
3044 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3045 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3046 offsetof(CERT_NAME_BLOB, pbData) };
3047 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
3049 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3050 pvStructInfo, *pcbStructInfo, pcbDecoded);
3052 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3053 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3054 entries ? entries->rgItems : NULL);
3055 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3056 return ret;
3059 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3060 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3061 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3063 BOOL ret;
3065 __TRY
3067 struct AsnDecodeSequenceItem items[] = {
3068 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3069 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3070 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3071 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3072 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3073 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3074 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3075 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3076 sizeof(struct GenericArray), TRUE, TRUE,
3077 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3080 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3081 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3082 pcbStructInfo, NULL, NULL);
3084 __EXCEPT_PAGE_FAULT
3086 SetLastError(STATUS_ACCESS_VIOLATION);
3087 ret = FALSE;
3089 __ENDTRY
3090 return ret;
3093 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3094 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3095 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3097 BOOL ret;
3099 __TRY
3101 struct AsnDecodeSequenceItem items[] = {
3102 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3103 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3104 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3105 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3106 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3109 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3110 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3111 pcbStructInfo, NULL, NULL);
3113 __EXCEPT_PAGE_FAULT
3115 SetLastError(STATUS_ACCESS_VIOLATION);
3116 ret = FALSE;
3118 __ENDTRY
3119 return ret;
3122 #define RSA1_MAGIC 0x31415352
3124 struct DECODED_RSA_PUB_KEY
3126 DWORD pubexp;
3127 CRYPT_INTEGER_BLOB modulus;
3130 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3131 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3132 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3134 BOOL ret;
3136 __TRY
3138 struct AsnDecodeSequenceItem items[] = {
3139 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3140 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3141 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3142 0 },
3143 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3144 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3146 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3147 DWORD size = 0;
3149 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3150 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3151 &size, NULL, NULL);
3152 if (ret)
3154 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3155 decodedKey->modulus.cbData;
3157 if (!pvStructInfo)
3159 *pcbStructInfo = bytesNeeded;
3160 ret = TRUE;
3162 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3163 pvStructInfo, pcbStructInfo, bytesNeeded)))
3165 BLOBHEADER *hdr;
3166 RSAPUBKEY *rsaPubKey;
3168 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3169 pvStructInfo = *(BYTE **)pvStructInfo;
3170 hdr = (BLOBHEADER *)pvStructInfo;
3171 hdr->bType = PUBLICKEYBLOB;
3172 hdr->bVersion = CUR_BLOB_VERSION;
3173 hdr->reserved = 0;
3174 hdr->aiKeyAlg = CALG_RSA_KEYX;
3175 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3176 sizeof(BLOBHEADER));
3177 rsaPubKey->magic = RSA1_MAGIC;
3178 rsaPubKey->pubexp = decodedKey->pubexp;
3179 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3180 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3181 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3182 decodedKey->modulus.cbData);
3184 LocalFree(decodedKey);
3187 __EXCEPT_PAGE_FAULT
3189 SetLastError(STATUS_ACCESS_VIOLATION);
3190 ret = FALSE;
3192 __ENDTRY
3193 return ret;
3196 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
3197 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3198 DWORD *pcbDecoded)
3200 BOOL ret;
3201 DWORD bytesNeeded, dataLen;
3203 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3204 pvStructInfo, *pcbStructInfo, pcbDecoded);
3206 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3208 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3210 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3211 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
3212 else
3213 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
3214 if (pcbDecoded)
3215 *pcbDecoded = 1 + lenBytes + dataLen;
3216 if (!pvStructInfo)
3217 *pcbStructInfo = bytesNeeded;
3218 else if (*pcbStructInfo < bytesNeeded)
3220 SetLastError(ERROR_MORE_DATA);
3221 *pcbStructInfo = bytesNeeded;
3222 ret = FALSE;
3224 else
3226 CRYPT_DATA_BLOB *blob;
3228 *pcbStructInfo = bytesNeeded;
3229 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3230 blob->cbData = dataLen;
3231 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3232 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
3233 else
3235 assert(blob->pbData);
3236 if (blob->cbData)
3237 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
3238 blob->cbData);
3242 return ret;
3245 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
3246 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3247 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3249 BOOL ret;
3251 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3252 pDecodePara, pvStructInfo, *pcbStructInfo);
3254 __TRY
3256 DWORD bytesNeeded;
3258 if (!cbEncoded)
3260 SetLastError(CRYPT_E_ASN1_CORRUPT);
3261 ret = FALSE;
3263 else if (pbEncoded[0] != ASN_OCTETSTRING)
3265 SetLastError(CRYPT_E_ASN1_BADTAG);
3266 ret = FALSE;
3268 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3269 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3271 if (!pvStructInfo)
3272 *pcbStructInfo = bytesNeeded;
3273 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3274 pvStructInfo, pcbStructInfo, bytesNeeded)))
3276 CRYPT_DATA_BLOB *blob;
3278 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3279 pvStructInfo = *(BYTE **)pvStructInfo;
3280 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3281 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
3282 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3283 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3284 &bytesNeeded, NULL);
3288 __EXCEPT_PAGE_FAULT
3290 SetLastError(STATUS_ACCESS_VIOLATION);
3291 ret = FALSE;
3293 __ENDTRY
3294 return ret;
3297 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3298 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3300 BOOL ret;
3302 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3303 pvStructInfo, *pcbStructInfo, pcbDecoded);
3305 if (pbEncoded[0] == ASN_BITSTRING)
3307 DWORD bytesNeeded, dataLen;
3308 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3310 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3312 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3313 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3314 else
3315 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3316 if (pcbDecoded)
3317 *pcbDecoded = 1 + lenBytes + dataLen;
3318 if (!pvStructInfo)
3319 *pcbStructInfo = bytesNeeded;
3320 else if (*pcbStructInfo < bytesNeeded)
3322 *pcbStructInfo = bytesNeeded;
3323 SetLastError(ERROR_MORE_DATA);
3324 ret = FALSE;
3326 else
3328 CRYPT_BIT_BLOB *blob;
3330 *pcbStructInfo = bytesNeeded;
3331 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3332 blob->cbData = dataLen - 1;
3333 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3334 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3336 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3338 else
3340 assert(blob->pbData);
3341 if (blob->cbData)
3343 BYTE mask = 0xff << blob->cUnusedBits;
3345 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3346 blob->cbData);
3347 blob->pbData[blob->cbData - 1] &= mask;
3353 else
3355 SetLastError(CRYPT_E_ASN1_BADTAG);
3356 ret = FALSE;
3358 TRACE("returning %d (%08x)\n", ret, GetLastError());
3359 return ret;
3362 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3363 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3364 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3366 BOOL ret;
3368 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3369 pDecodePara, pvStructInfo, pcbStructInfo);
3371 __TRY
3373 DWORD bytesNeeded;
3375 if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3376 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3378 if (!pvStructInfo)
3379 *pcbStructInfo = bytesNeeded;
3380 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3381 pvStructInfo, pcbStructInfo, bytesNeeded)))
3383 CRYPT_BIT_BLOB *blob;
3385 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3386 pvStructInfo = *(BYTE **)pvStructInfo;
3387 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3388 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3389 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3390 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3391 &bytesNeeded, NULL);
3395 __EXCEPT_PAGE_FAULT
3397 SetLastError(STATUS_ACCESS_VIOLATION);
3398 ret = FALSE;
3400 __ENDTRY
3401 TRACE("returning %d (%08x)\n", ret, GetLastError());
3402 return ret;
3405 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
3406 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3407 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3409 BOOL ret;
3410 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3411 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3412 DWORD size = sizeof(buf);
3414 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3415 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, buf,
3416 &size, pcbDecoded);
3417 if (ret)
3419 if (!pvStructInfo)
3420 *pcbStructInfo = sizeof(int);
3421 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3423 int val, i;
3425 if (blob->pbData[blob->cbData - 1] & 0x80)
3427 /* initialize to a negative value to sign-extend */
3428 val = -1;
3430 else
3431 val = 0;
3432 for (i = 0; i < blob->cbData; i++)
3434 val <<= 8;
3435 val |= blob->pbData[blob->cbData - i - 1];
3437 memcpy(pvStructInfo, &val, sizeof(int));
3440 else if (GetLastError() == ERROR_MORE_DATA)
3441 SetLastError(CRYPT_E_ASN1_LARGE);
3442 return ret;
3445 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3446 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3447 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3449 BOOL ret;
3451 __TRY
3453 DWORD bytesNeeded;
3455 if (!cbEncoded)
3457 SetLastError(CRYPT_E_ASN1_CORRUPT);
3458 ret = FALSE;
3460 else if (pbEncoded[0] != ASN_INTEGER)
3462 SetLastError(CRYPT_E_ASN1_BADTAG);
3463 ret = FALSE;
3465 else
3466 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3467 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3468 if (ret)
3470 if (!pvStructInfo)
3471 *pcbStructInfo = bytesNeeded;
3472 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3473 pvStructInfo, pcbStructInfo, bytesNeeded)))
3475 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3476 pvStructInfo = *(BYTE **)pvStructInfo;
3477 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3478 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3479 &bytesNeeded, NULL);
3483 __EXCEPT_PAGE_FAULT
3485 SetLastError(STATUS_ACCESS_VIOLATION);
3486 ret = FALSE;
3488 __ENDTRY
3489 return ret;
3492 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3493 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3494 DWORD *pcbDecoded)
3496 BOOL ret;
3497 DWORD bytesNeeded, dataLen;
3499 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3501 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3503 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3504 if (pcbDecoded)
3505 *pcbDecoded = 1 + lenBytes + dataLen;
3506 if (!pvStructInfo)
3507 *pcbStructInfo = bytesNeeded;
3508 else if (*pcbStructInfo < bytesNeeded)
3510 *pcbStructInfo = bytesNeeded;
3511 SetLastError(ERROR_MORE_DATA);
3512 ret = FALSE;
3514 else
3516 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3518 *pcbStructInfo = bytesNeeded;
3519 blob->cbData = dataLen;
3520 assert(blob->pbData);
3521 if (blob->cbData)
3523 DWORD i;
3525 for (i = 0; i < blob->cbData; i++)
3527 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3528 dataLen - i - 1);
3533 return ret;
3536 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3537 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3538 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3540 BOOL ret;
3542 __TRY
3544 DWORD bytesNeeded;
3546 if (pbEncoded[0] != ASN_INTEGER)
3548 SetLastError(CRYPT_E_ASN1_BADTAG);
3549 ret = FALSE;
3551 else
3552 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3553 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3554 if (ret)
3556 if (!pvStructInfo)
3557 *pcbStructInfo = bytesNeeded;
3558 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3559 pvStructInfo, pcbStructInfo, bytesNeeded)))
3561 CRYPT_INTEGER_BLOB *blob;
3563 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3564 pvStructInfo = *(BYTE **)pvStructInfo;
3565 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3566 blob->pbData = (BYTE *)pvStructInfo +
3567 sizeof(CRYPT_INTEGER_BLOB);
3568 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3569 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3570 &bytesNeeded, NULL);
3574 __EXCEPT_PAGE_FAULT
3576 SetLastError(STATUS_ACCESS_VIOLATION);
3577 ret = FALSE;
3579 __ENDTRY
3580 return ret;
3583 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3584 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3585 DWORD *pcbDecoded)
3587 BOOL ret;
3589 if (pbEncoded[0] == ASN_INTEGER)
3591 DWORD bytesNeeded, dataLen;
3593 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3595 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3597 if (pcbDecoded)
3598 *pcbDecoded = 1 + lenBytes + dataLen;
3599 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3600 if (!pvStructInfo)
3601 *pcbStructInfo = bytesNeeded;
3602 else if (*pcbStructInfo < bytesNeeded)
3604 *pcbStructInfo = bytesNeeded;
3605 SetLastError(ERROR_MORE_DATA);
3606 ret = FALSE;
3608 else
3610 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3612 *pcbStructInfo = bytesNeeded;
3613 blob->cbData = dataLen;
3614 assert(blob->pbData);
3615 /* remove leading zero byte if it exists */
3616 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3618 blob->cbData--;
3619 blob->pbData++;
3621 if (blob->cbData)
3623 DWORD i;
3625 for (i = 0; i < blob->cbData; i++)
3627 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3628 dataLen - i - 1);
3634 else
3636 SetLastError(CRYPT_E_ASN1_BADTAG);
3637 ret = FALSE;
3639 return ret;
3642 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3643 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3644 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3646 BOOL ret;
3648 __TRY
3650 DWORD bytesNeeded;
3652 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
3653 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3655 if (!pvStructInfo)
3656 *pcbStructInfo = bytesNeeded;
3657 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3658 pvStructInfo, pcbStructInfo, bytesNeeded)))
3660 CRYPT_INTEGER_BLOB *blob;
3662 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3663 pvStructInfo = *(BYTE **)pvStructInfo;
3664 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3665 blob->pbData = (BYTE *)pvStructInfo +
3666 sizeof(CRYPT_INTEGER_BLOB);
3667 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
3668 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3669 &bytesNeeded, NULL);
3673 __EXCEPT_PAGE_FAULT
3675 SetLastError(STATUS_ACCESS_VIOLATION);
3676 ret = FALSE;
3678 __ENDTRY
3679 return ret;
3682 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3683 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3684 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3686 BOOL ret;
3688 if (!pvStructInfo)
3690 *pcbStructInfo = sizeof(int);
3691 return TRUE;
3693 __TRY
3695 if (pbEncoded[0] == ASN_ENUMERATED)
3697 unsigned int val = 0, i;
3699 if (cbEncoded <= 1)
3701 SetLastError(CRYPT_E_ASN1_EOD);
3702 ret = FALSE;
3704 else if (pbEncoded[1] == 0)
3706 SetLastError(CRYPT_E_ASN1_CORRUPT);
3707 ret = FALSE;
3709 else
3711 /* A little strange looking, but we have to accept a sign byte:
3712 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3713 * assuming a small length is okay here, it has to be in short
3714 * form.
3716 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3718 SetLastError(CRYPT_E_ASN1_LARGE);
3719 return FALSE;
3721 for (i = 0; i < pbEncoded[1]; i++)
3723 val <<= 8;
3724 val |= pbEncoded[2 + i];
3726 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3727 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3729 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3730 pvStructInfo = *(BYTE **)pvStructInfo;
3731 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3735 else
3737 SetLastError(CRYPT_E_ASN1_BADTAG);
3738 ret = FALSE;
3741 __EXCEPT_PAGE_FAULT
3743 SetLastError(STATUS_ACCESS_VIOLATION);
3744 ret = FALSE;
3746 __ENDTRY
3747 return ret;
3750 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3751 * if it fails.
3753 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3754 do { \
3755 BYTE i; \
3757 (word) = 0; \
3758 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3760 if (!isdigit(*(pbEncoded))) \
3762 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3763 ret = FALSE; \
3765 else \
3767 (word) *= 10; \
3768 (word) += *(pbEncoded)++ - '0'; \
3771 } while (0)
3773 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3774 SYSTEMTIME *sysTime)
3776 BOOL ret = TRUE;
3778 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3780 WORD hours, minutes = 0;
3781 BYTE sign = *pbEncoded++;
3783 len--;
3784 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3785 if (ret && hours >= 24)
3787 SetLastError(CRYPT_E_ASN1_CORRUPT);
3788 ret = FALSE;
3790 else if (len >= 2)
3792 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3793 if (ret && minutes >= 60)
3795 SetLastError(CRYPT_E_ASN1_CORRUPT);
3796 ret = FALSE;
3799 if (ret)
3801 if (sign == '+')
3803 sysTime->wHour += hours;
3804 sysTime->wMinute += minutes;
3806 else
3808 if (hours > sysTime->wHour)
3810 sysTime->wDay--;
3811 sysTime->wHour = 24 - (hours - sysTime->wHour);
3813 else
3814 sysTime->wHour -= hours;
3815 if (minutes > sysTime->wMinute)
3817 sysTime->wHour--;
3818 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3820 else
3821 sysTime->wMinute -= minutes;
3825 return ret;
3828 #define MIN_ENCODED_TIME_LENGTH 10
3830 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3831 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3832 DWORD *pcbDecoded)
3834 BOOL ret = FALSE;
3836 if (pbEncoded[0] == ASN_UTCTIME)
3838 if (cbEncoded <= 1)
3839 SetLastError(CRYPT_E_ASN1_EOD);
3840 else if (pbEncoded[1] > 0x7f)
3842 /* long-form date strings really can't be valid */
3843 SetLastError(CRYPT_E_ASN1_CORRUPT);
3845 else
3847 SYSTEMTIME sysTime = { 0 };
3848 BYTE len = pbEncoded[1];
3850 if (len < MIN_ENCODED_TIME_LENGTH)
3851 SetLastError(CRYPT_E_ASN1_CORRUPT);
3852 else
3854 ret = TRUE;
3855 if (pcbDecoded)
3856 *pcbDecoded = 2 + len;
3857 pbEncoded += 2;
3858 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3859 if (sysTime.wYear >= 50)
3860 sysTime.wYear += 1900;
3861 else
3862 sysTime.wYear += 2000;
3863 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3864 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3865 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3866 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3867 if (ret && len > 0)
3869 if (len >= 2 && isdigit(*pbEncoded) &&
3870 isdigit(*(pbEncoded + 1)))
3871 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3872 sysTime.wSecond);
3873 else if (isdigit(*pbEncoded))
3874 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3875 sysTime.wSecond);
3876 if (ret)
3877 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3878 &sysTime);
3880 if (ret)
3882 if (!pvStructInfo)
3883 *pcbStructInfo = sizeof(FILETIME);
3884 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3885 sizeof(FILETIME))))
3886 ret = SystemTimeToFileTime(&sysTime,
3887 (FILETIME *)pvStructInfo);
3892 else
3893 SetLastError(CRYPT_E_ASN1_BADTAG);
3894 return ret;
3897 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3898 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3899 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3901 BOOL ret = FALSE;
3903 __TRY
3905 DWORD bytesNeeded;
3907 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3908 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3909 if (ret)
3911 if (!pvStructInfo)
3912 *pcbStructInfo = bytesNeeded;
3913 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3914 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3916 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3917 pvStructInfo = *(BYTE **)pvStructInfo;
3918 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3919 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3920 &bytesNeeded, NULL);
3924 __EXCEPT_PAGE_FAULT
3926 SetLastError(STATUS_ACCESS_VIOLATION);
3928 __ENDTRY
3929 return ret;
3932 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3933 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3934 DWORD *pcbDecoded)
3936 BOOL ret = FALSE;
3938 if (pbEncoded[0] == ASN_GENERALTIME)
3940 if (cbEncoded <= 1)
3941 SetLastError(CRYPT_E_ASN1_EOD);
3942 else if (pbEncoded[1] > 0x7f)
3944 /* long-form date strings really can't be valid */
3945 SetLastError(CRYPT_E_ASN1_CORRUPT);
3947 else
3949 BYTE len = pbEncoded[1];
3951 if (len < MIN_ENCODED_TIME_LENGTH)
3952 SetLastError(CRYPT_E_ASN1_CORRUPT);
3953 else
3955 SYSTEMTIME sysTime = { 0 };
3957 ret = TRUE;
3958 if (pcbDecoded)
3959 *pcbDecoded = 2 + len;
3960 pbEncoded += 2;
3961 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3962 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3963 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3964 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3965 if (ret && len > 0)
3967 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3968 sysTime.wMinute);
3969 if (ret && len > 0)
3970 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3971 sysTime.wSecond);
3972 if (ret && len > 0 && (*pbEncoded == '.' ||
3973 *pbEncoded == ','))
3975 BYTE digits;
3977 pbEncoded++;
3978 len--;
3979 /* workaround macro weirdness */
3980 digits = min(len, 3);
3981 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3982 sysTime.wMilliseconds);
3984 if (ret)
3985 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3986 &sysTime);
3988 if (ret)
3990 if (!pvStructInfo)
3991 *pcbStructInfo = sizeof(FILETIME);
3992 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3993 sizeof(FILETIME))))
3994 ret = SystemTimeToFileTime(&sysTime,
3995 (FILETIME *)pvStructInfo);
4000 else
4001 SetLastError(CRYPT_E_ASN1_BADTAG);
4002 return ret;
4005 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4006 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4007 DWORD *pcbDecoded)
4009 BOOL ret;
4010 InternalDecodeFunc decode = NULL;
4012 if (pbEncoded[0] == ASN_UTCTIME)
4013 decode = CRYPT_AsnDecodeUtcTimeInternal;
4014 else if (pbEncoded[0] == ASN_GENERALTIME)
4015 decode = CRYPT_AsnDecodeGeneralizedTime;
4016 if (decode)
4017 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
4018 pcbStructInfo, pcbDecoded);
4019 else
4021 SetLastError(CRYPT_E_ASN1_BADTAG);
4022 ret = FALSE;
4024 return ret;
4027 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
4028 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4029 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4031 BOOL ret;
4033 __TRY
4035 DWORD bytesNeeded;
4037 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4038 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4039 if (ret)
4041 if (!pvStructInfo)
4042 *pcbStructInfo = bytesNeeded;
4043 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4044 pvStructInfo, pcbStructInfo, bytesNeeded)))
4046 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4047 pvStructInfo = *(BYTE **)pvStructInfo;
4048 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4049 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4050 &bytesNeeded, NULL);
4054 __EXCEPT_PAGE_FAULT
4056 SetLastError(STATUS_ACCESS_VIOLATION);
4057 ret = FALSE;
4059 __ENDTRY
4060 return ret;
4063 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
4064 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4065 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4067 BOOL ret = TRUE;
4069 __TRY
4071 if (pbEncoded[0] == ASN_SEQUENCEOF)
4073 DWORD bytesNeeded, dataLen, remainingLen, cValue;
4075 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4077 BYTE lenBytes;
4078 const BYTE *ptr;
4080 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4081 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
4082 cValue = 0;
4083 ptr = pbEncoded + 1 + lenBytes;
4084 remainingLen = dataLen;
4085 while (ret && remainingLen)
4087 DWORD nextLen;
4089 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4090 if (ret)
4092 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4094 remainingLen -= 1 + nextLenBytes + nextLen;
4095 ptr += 1 + nextLenBytes + nextLen;
4096 bytesNeeded += sizeof(CRYPT_DER_BLOB);
4097 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
4098 bytesNeeded += 1 + nextLenBytes + nextLen;
4099 cValue++;
4102 if (ret)
4104 CRYPT_SEQUENCE_OF_ANY *seq;
4105 BYTE *nextPtr;
4106 DWORD i;
4108 if (!pvStructInfo)
4109 *pcbStructInfo = bytesNeeded;
4110 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4111 pvStructInfo, pcbStructInfo, bytesNeeded)))
4113 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4114 pvStructInfo = *(BYTE **)pvStructInfo;
4115 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
4116 seq->cValue = cValue;
4117 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
4118 sizeof(*seq));
4119 nextPtr = (BYTE *)seq->rgValue +
4120 cValue * sizeof(CRYPT_DER_BLOB);
4121 ptr = pbEncoded + 1 + lenBytes;
4122 remainingLen = dataLen;
4123 i = 0;
4124 while (ret && remainingLen)
4126 DWORD nextLen;
4128 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4129 if (ret)
4131 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4133 seq->rgValue[i].cbData = 1 + nextLenBytes +
4134 nextLen;
4135 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4136 seq->rgValue[i].pbData = (BYTE *)ptr;
4137 else
4139 seq->rgValue[i].pbData = nextPtr;
4140 memcpy(nextPtr, ptr, 1 + nextLenBytes +
4141 nextLen);
4142 nextPtr += 1 + nextLenBytes + nextLen;
4144 remainingLen -= 1 + nextLenBytes + nextLen;
4145 ptr += 1 + nextLenBytes + nextLen;
4146 i++;
4153 else
4155 SetLastError(CRYPT_E_ASN1_BADTAG);
4156 ret = FALSE;
4159 __EXCEPT_PAGE_FAULT
4161 SetLastError(STATUS_ACCESS_VIOLATION);
4162 ret = FALSE;
4164 __ENDTRY
4165 return ret;
4168 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4169 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4170 DWORD *pcbDecoded)
4172 BOOL ret;
4174 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
4176 DWORD bytesNeeded, dataLen;
4178 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4180 struct AsnArrayDescriptor arrayDesc = {
4181 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
4182 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
4183 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
4184 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4185 DWORD nameLen;
4187 if (dataLen)
4189 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4190 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4191 0, NULL, NULL, &nameLen, NULL, NULL);
4192 /* The CERT_ALT_NAME_INFO's size is included by CRYPT_AsnDecodeArray
4193 * as the sizeof(struct GenericArray), so don't include it in the
4194 * total bytes needed.
4196 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
4197 sizeof(CERT_ALT_NAME_INFO);
4199 else
4200 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
4201 if (pcbDecoded)
4202 *pcbDecoded = 1 + lenBytes + dataLen;
4203 if (!pvStructInfo)
4204 *pcbStructInfo = bytesNeeded;
4205 else if (*pcbStructInfo < bytesNeeded)
4207 *pcbStructInfo = bytesNeeded;
4208 SetLastError(ERROR_MORE_DATA);
4209 ret = FALSE;
4211 else
4213 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
4215 *pcbStructInfo = bytesNeeded;
4216 if (dataLen)
4218 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
4219 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4220 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4221 0, NULL, &name->u.FullName, &nameLen, NULL,
4222 name->u.FullName.rgAltEntry);
4224 else
4225 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
4229 else
4231 SetLastError(CRYPT_E_ASN1_BADTAG);
4232 ret = FALSE;
4234 return ret;
4237 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
4238 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4240 struct AsnDecodeSequenceItem items[] = {
4241 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
4242 DistPointName), CRYPT_AsnDecodeDistPointName,
4243 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
4244 DistPointName.u.FullName.rgAltEntry), 0 },
4245 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
4246 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
4247 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
4248 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
4249 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
4250 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
4252 BOOL ret;
4254 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4255 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4256 pcbDecoded, NULL);
4257 return ret;
4260 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
4261 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4262 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4264 BOOL ret;
4266 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4267 pDecodePara, pvStructInfo, *pcbStructInfo);
4269 __TRY
4271 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4272 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
4273 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
4275 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4276 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4278 __EXCEPT_PAGE_FAULT
4280 SetLastError(STATUS_ACCESS_VIOLATION);
4281 ret = FALSE;
4283 __ENDTRY
4284 return ret;
4287 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
4288 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4289 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4291 BOOL ret;
4293 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4294 pDecodePara, pvStructInfo, *pcbStructInfo);
4296 __TRY
4298 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4299 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4301 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4302 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4304 __EXCEPT_PAGE_FAULT
4306 SetLastError(STATUS_ACCESS_VIOLATION);
4307 ret = FALSE;
4309 __ENDTRY
4310 return ret;
4313 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4314 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4315 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4317 BOOL ret;
4319 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4320 pDecodePara, pvStructInfo, *pcbStructInfo);
4322 __TRY
4324 struct AsnDecodeSequenceItem items[] = {
4325 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4326 DistPointName), CRYPT_AsnDecodeDistPointName,
4327 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4328 offsetof(CRL_ISSUING_DIST_POINT,
4329 DistPointName.u.FullName.rgAltEntry), 0 },
4330 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4331 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4332 FALSE, 0 },
4333 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4334 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4335 FALSE, 0 },
4336 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4337 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4338 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4339 OnlySomeReasonFlags.pbData), 0 },
4340 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4341 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4344 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4345 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4346 pcbStructInfo, NULL, NULL);
4348 __EXCEPT_PAGE_FAULT
4350 SetLastError(STATUS_ACCESS_VIOLATION);
4351 ret = FALSE;
4353 __ENDTRY
4354 return ret;
4357 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
4358 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4359 DWORD *pcbDecoded)
4361 BOOL ret = FALSE;
4363 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4364 pvStructInfo, *pcbStructInfo, pcbDecoded);
4366 if (!cbEncoded)
4368 SetLastError(CRYPT_E_ASN1_EOD);
4369 return FALSE;
4371 if (pbEncoded[0] != (ASN_CONTEXT | 1))
4373 SetLastError(CRYPT_E_ASN1_BADTAG);
4374 return FALSE;
4376 /* The BOOL is implicit: if the integer is present, then it's TRUE */
4377 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
4378 pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo,
4379 pcbDecoded);
4380 if (ret && pvStructInfo)
4381 *(BOOL *)pvStructInfo = TRUE;
4382 TRACE("returning %d\n", ret);
4383 return ret;
4386 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
4387 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4388 DWORD *pcbDecoded)
4390 BOOL ret;
4391 struct AsnDecodeSequenceItem items[] = {
4392 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
4393 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
4394 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
4395 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
4396 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
4397 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
4398 CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0,
4399 0 },
4401 CERT_GENERAL_SUBTREE *subtree = (CERT_GENERAL_SUBTREE *)pvStructInfo;
4403 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4404 pvStructInfo, *pcbStructInfo, pcbDecoded);
4406 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4407 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4408 pcbDecoded, subtree ? (BYTE *)subtree->Base.u.pwszURL : NULL);
4409 if (pcbDecoded)
4411 TRACE("%d\n", *pcbDecoded);
4412 if (*pcbDecoded < cbEncoded)
4413 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
4414 *(pbEncoded + *pcbDecoded + 1));
4416 TRACE("returning %d\n", ret);
4417 return ret;
4420 static BOOL CRYPT_AsnDecodeSubtreeArray(const BYTE *pbEncoded,
4421 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4422 DWORD *pcbDecoded)
4424 BOOL ret = TRUE;
4425 struct AsnArrayDescriptor arrayDesc = { 0,
4426 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4427 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4428 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4430 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4431 pvStructInfo, *pcbStructInfo, pcbDecoded);
4433 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4434 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4435 array ? array->rgItems : NULL);
4436 return ret;
4440 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
4441 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4442 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4444 BOOL ret = FALSE;
4446 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4447 pDecodePara, pvStructInfo, *pcbStructInfo);
4449 __TRY
4451 struct AsnDecodeSequenceItem items[] = {
4452 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4453 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
4454 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4455 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
4456 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
4457 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4458 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4459 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
4462 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4463 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4464 pcbStructInfo, NULL, NULL);
4466 __EXCEPT_PAGE_FAULT
4468 SetLastError(STATUS_ACCESS_VIOLATION);
4470 __ENDTRY
4471 return ret;
4474 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
4475 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4476 DWORD *pcbDecoded)
4478 BOOL ret;
4479 struct AsnDecodeSequenceItem items[] = {
4480 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4481 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4482 Issuer.pbData) },
4483 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4484 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4485 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4487 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4488 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4490 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4491 pvStructInfo, *pcbStructInfo, pcbDecoded);
4493 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4494 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4495 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4496 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4498 SetLastError(CRYPT_E_ASN1_CORRUPT);
4499 ret = FALSE;
4501 TRACE("returning %d\n", ret);
4502 return ret;
4505 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4506 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4507 DWORD *pcbDecoded)
4509 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4510 struct AsnDecodeSequenceItem items[] = {
4511 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4512 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4513 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4514 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4515 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4516 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4517 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4518 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4519 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4520 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4521 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4522 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4523 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4524 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4525 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4526 HashEncryptionAlgorithm.pszObjId), 0 },
4527 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4528 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4529 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4530 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4531 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4532 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4533 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4535 BOOL ret;
4537 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4538 pvStructInfo, *pcbStructInfo);
4540 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4541 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4542 pcbDecoded, info ? info->Issuer.pbData : NULL);
4543 return ret;
4546 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4547 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4548 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4550 BOOL ret = FALSE;
4552 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4553 pDecodePara, pvStructInfo, *pcbStructInfo);
4555 __TRY
4557 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4558 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4559 if (ret && pvStructInfo)
4561 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4562 pcbStructInfo, *pcbStructInfo);
4563 if (ret)
4565 CMSG_SIGNER_INFO *info;
4567 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4568 pvStructInfo = *(BYTE **)pvStructInfo;
4569 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4570 info->Issuer.pbData = ((BYTE *)info +
4571 sizeof(CMSG_SIGNER_INFO));
4572 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4573 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4574 pcbStructInfo, NULL);
4578 __EXCEPT_PAGE_FAULT
4580 SetLastError(STATUS_ACCESS_VIOLATION);
4582 __ENDTRY
4583 TRACE("returning %d\n", ret);
4584 return ret;
4587 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
4588 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4589 DWORD *pcbDecoded)
4591 CERT_ID *id = (CERT_ID *)pvStructInfo;
4592 BOOL ret = FALSE;
4594 if (*pbEncoded == ASN_SEQUENCEOF)
4596 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
4597 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
4598 if (ret)
4600 if (id)
4601 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
4602 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
4603 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4604 sizeof(CERT_ISSUER_SERIAL_NUMBER);
4605 else
4606 *pcbStructInfo = sizeof(CERT_ID);
4609 else if (*pbEncoded == (ASN_CONTEXT | 0))
4611 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
4612 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
4613 if (ret)
4615 if (id)
4616 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
4617 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
4618 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4619 sizeof(CRYPT_DATA_BLOB);
4620 else
4621 *pcbStructInfo = sizeof(CERT_ID);
4624 else
4625 SetLastError(CRYPT_E_ASN1_BADTAG);
4626 return ret;
4629 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
4630 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4631 DWORD *pcbDecoded)
4633 CMSG_CMS_SIGNER_INFO *info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4634 struct AsnDecodeSequenceItem items[] = {
4635 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
4636 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4637 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
4638 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
4639 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
4640 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
4641 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4642 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4643 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4644 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
4645 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4646 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4647 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
4648 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4649 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
4650 HashEncryptionAlgorithm.pszObjId), 0 },
4651 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
4652 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4653 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
4654 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4655 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
4656 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4657 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4659 BOOL ret;
4661 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4662 pvStructInfo, *pcbStructInfo);
4664 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4665 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4666 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
4667 return ret;
4670 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
4671 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4672 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4674 BOOL ret = FALSE;
4676 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4677 pDecodePara, pvStructInfo, *pcbStructInfo);
4679 __TRY
4681 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
4682 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4683 if (ret && pvStructInfo)
4685 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4686 pcbStructInfo, *pcbStructInfo);
4687 if (ret)
4689 CMSG_CMS_SIGNER_INFO *info;
4691 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4692 pvStructInfo = *(BYTE **)pvStructInfo;
4693 info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4694 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
4695 sizeof(CMSG_CMS_SIGNER_INFO));
4696 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
4697 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4698 pcbStructInfo, NULL);
4702 __EXCEPT_PAGE_FAULT
4704 SetLastError(STATUS_ACCESS_VIOLATION);
4706 __ENDTRY
4707 TRACE("returning %d\n", ret);
4708 return ret;
4711 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
4712 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4714 BOOL ret;
4715 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4716 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
4717 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
4718 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4720 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4721 pvStructInfo, *pcbStructInfo, pcbDecoded);
4723 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4724 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4725 array ? array->rgItems : NULL);
4726 return ret;
4729 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4730 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4731 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4733 BOOL ret = FALSE;
4734 struct AsnDecodeSequenceItem items[] = {
4735 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4736 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4737 /* Placeholder for the hash algorithms - redundant with those in the
4738 * signers, so just ignore them.
4740 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4741 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4742 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4743 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4744 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4745 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4746 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4747 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4748 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4749 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4750 sizeof(struct GenericArray), TRUE, TRUE,
4751 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4752 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4753 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4754 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4757 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4758 pDecodePara, signedInfo, *pcbSignedInfo);
4760 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4761 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
4762 NULL, NULL);
4763 TRACE("returning %d\n", ret);
4764 return ret;
4767 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4768 LPCSTR lpszStructType)
4770 CryptDecodeObjectExFunc decodeFunc = NULL;
4772 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4773 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4775 SetLastError(ERROR_FILE_NOT_FOUND);
4776 return NULL;
4778 if (!HIWORD(lpszStructType))
4780 switch (LOWORD(lpszStructType))
4782 case LOWORD(X509_CERT):
4783 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4784 break;
4785 case LOWORD(X509_CERT_TO_BE_SIGNED):
4786 decodeFunc = CRYPT_AsnDecodeCert;
4787 break;
4788 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4789 decodeFunc = CRYPT_AsnDecodeCRL;
4790 break;
4791 case LOWORD(X509_EXTENSIONS):
4792 decodeFunc = CRYPT_AsnDecodeExtensions;
4793 break;
4794 case LOWORD(X509_NAME_VALUE):
4795 decodeFunc = CRYPT_AsnDecodeNameValue;
4796 break;
4797 case LOWORD(X509_NAME):
4798 decodeFunc = CRYPT_AsnDecodeName;
4799 break;
4800 case LOWORD(X509_PUBLIC_KEY_INFO):
4801 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4802 break;
4803 case LOWORD(X509_AUTHORITY_KEY_ID):
4804 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4805 break;
4806 case LOWORD(X509_ALTERNATE_NAME):
4807 decodeFunc = CRYPT_AsnDecodeAltName;
4808 break;
4809 case LOWORD(X509_BASIC_CONSTRAINTS):
4810 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4811 break;
4812 case LOWORD(X509_BASIC_CONSTRAINTS2):
4813 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4814 break;
4815 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4816 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4817 break;
4818 case LOWORD(X509_UNICODE_NAME):
4819 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4820 break;
4821 case LOWORD(PKCS_ATTRIBUTE):
4822 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4823 break;
4824 case LOWORD(X509_UNICODE_NAME_VALUE):
4825 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4826 break;
4827 case LOWORD(X509_OCTET_STRING):
4828 decodeFunc = CRYPT_AsnDecodeOctets;
4829 break;
4830 case LOWORD(X509_BITS):
4831 case LOWORD(X509_KEY_USAGE):
4832 decodeFunc = CRYPT_AsnDecodeBits;
4833 break;
4834 case LOWORD(X509_INTEGER):
4835 decodeFunc = CRYPT_AsnDecodeInt;
4836 break;
4837 case LOWORD(X509_MULTI_BYTE_INTEGER):
4838 decodeFunc = CRYPT_AsnDecodeInteger;
4839 break;
4840 case LOWORD(X509_MULTI_BYTE_UINT):
4841 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4842 break;
4843 case LOWORD(X509_ENUMERATED):
4844 decodeFunc = CRYPT_AsnDecodeEnumerated;
4845 break;
4846 case LOWORD(X509_CHOICE_OF_TIME):
4847 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4848 break;
4849 case LOWORD(X509_AUTHORITY_KEY_ID2):
4850 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4851 break;
4852 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4853 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
4854 break;
4855 case LOWORD(PKCS_CONTENT_INFO):
4856 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4857 break;
4858 case LOWORD(X509_SEQUENCE_OF_ANY):
4859 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4860 break;
4861 case LOWORD(PKCS_UTC_TIME):
4862 decodeFunc = CRYPT_AsnDecodeUtcTime;
4863 break;
4864 case LOWORD(X509_CRL_DIST_POINTS):
4865 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4866 break;
4867 case LOWORD(X509_ENHANCED_KEY_USAGE):
4868 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4869 break;
4870 case LOWORD(PKCS_CTL):
4871 decodeFunc = CRYPT_AsnDecodeCTL;
4872 break;
4873 case LOWORD(PKCS_SMIME_CAPABILITIES):
4874 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
4875 break;
4876 case LOWORD(PKCS_ATTRIBUTES):
4877 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4878 break;
4879 case LOWORD(X509_ISSUING_DIST_POINT):
4880 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4881 break;
4882 case LOWORD(X509_NAME_CONSTRAINTS):
4883 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4884 break;
4885 case LOWORD(PKCS7_SIGNER_INFO):
4886 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4887 break;
4888 case LOWORD(CMS_SIGNER_INFO):
4889 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
4890 break;
4893 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4894 decodeFunc = CRYPT_AsnDecodeExtensions;
4895 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4896 decodeFunc = CRYPT_AsnDecodeUtcTime;
4897 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4898 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
4899 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4900 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4901 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4902 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4903 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4904 decodeFunc = CRYPT_AsnDecodeEnumerated;
4905 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4906 decodeFunc = CRYPT_AsnDecodeBits;
4907 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4908 decodeFunc = CRYPT_AsnDecodeOctets;
4909 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4910 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4911 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4912 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4913 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4914 decodeFunc = CRYPT_AsnDecodeAltName;
4915 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4916 decodeFunc = CRYPT_AsnDecodeAltName;
4917 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4918 decodeFunc = CRYPT_AsnDecodeAltName;
4919 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4920 decodeFunc = CRYPT_AsnDecodeAltName;
4921 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4922 decodeFunc = CRYPT_AsnDecodeAltName;
4923 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4924 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4925 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4926 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4927 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4928 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4929 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4930 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4931 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4932 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
4933 else if (!strcmp(lpszStructType, szOID_CTL))
4934 decodeFunc = CRYPT_AsnDecodeCTL;
4935 return decodeFunc;
4938 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4939 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4941 static HCRYPTOIDFUNCSET set = NULL;
4942 CryptDecodeObjectFunc decodeFunc = NULL;
4944 if (!set)
4945 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4946 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4947 (void **)&decodeFunc, hFunc);
4948 return decodeFunc;
4951 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4952 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4954 static HCRYPTOIDFUNCSET set = NULL;
4955 CryptDecodeObjectExFunc decodeFunc = NULL;
4957 if (!set)
4958 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4959 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4960 (void **)&decodeFunc, hFunc);
4961 return decodeFunc;
4964 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4965 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4966 DWORD *pcbStructInfo)
4968 BOOL ret = FALSE;
4969 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4970 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4971 HCRYPTOIDFUNCADDR hFunc = NULL;
4973 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4974 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4975 pvStructInfo, pcbStructInfo);
4977 if (!pvStructInfo && !pcbStructInfo)
4979 SetLastError(ERROR_INVALID_PARAMETER);
4980 return FALSE;
4982 if (!cbEncoded)
4984 SetLastError(CRYPT_E_ASN1_EOD);
4985 return FALSE;
4987 if (cbEncoded > MAX_ENCODED_LEN)
4989 SetLastError(CRYPT_E_ASN1_LARGE);
4990 return FALSE;
4993 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4994 lpszStructType)))
4996 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4997 debugstr_a(lpszStructType));
4998 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4999 lpszStructType, &hFunc);
5000 if (!pCryptDecodeObject)
5001 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
5002 lpszStructType, &hFunc);
5004 if (pCryptDecodeObject)
5005 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5006 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5007 else if (pCryptDecodeObjectEx)
5008 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
5009 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
5010 pvStructInfo, pcbStructInfo);
5011 if (hFunc)
5012 CryptFreeOIDFunctionAddress(hFunc, 0);
5013 TRACE_(crypt)("returning %d\n", ret);
5014 return ret;
5017 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5018 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5019 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5021 BOOL ret = FALSE;
5022 CryptDecodeObjectExFunc decodeFunc;
5023 HCRYPTOIDFUNCADDR hFunc = NULL;
5025 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
5026 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5027 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5029 if (!pvStructInfo && !pcbStructInfo)
5031 SetLastError(ERROR_INVALID_PARAMETER);
5032 return FALSE;
5034 if (!cbEncoded)
5036 SetLastError(CRYPT_E_ASN1_EOD);
5037 return FALSE;
5039 if (cbEncoded > MAX_ENCODED_LEN)
5041 SetLastError(CRYPT_E_ASN1_LARGE);
5042 return FALSE;
5045 SetLastError(NOERROR);
5046 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5047 *(BYTE **)pvStructInfo = NULL;
5048 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
5049 if (!decodeFunc)
5051 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5052 debugstr_a(lpszStructType));
5053 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
5054 &hFunc);
5056 if (decodeFunc)
5057 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5058 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5059 else
5061 CryptDecodeObjectFunc pCryptDecodeObject =
5062 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
5064 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
5065 * directly, as that could cause an infinite loop.
5067 if (pCryptDecodeObject)
5069 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5071 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5072 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
5073 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5074 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
5075 ret = pCryptDecodeObject(dwCertEncodingType,
5076 lpszStructType, pbEncoded, cbEncoded, dwFlags,
5077 *(BYTE **)pvStructInfo, pcbStructInfo);
5079 else
5080 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5081 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5084 if (hFunc)
5085 CryptFreeOIDFunctionAddress(hFunc, 0);
5086 TRACE_(crypt)("returning %d\n", ret);
5087 return ret;