crypt32: Separate checking the tag of encoded bits from decoding the bits.
[wine/multimedia.git] / dlls / crypt32 / decode.c
blob465400812eff3785c16408c9e74fae6a793bde12
1 /*
2 * Copyright 2005-2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
33 #include "config.h"
34 #include "wine/port.h"
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
41 #define NONAMELESSUNION
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "winnls.h"
47 #include "snmp.h"
48 #include "wine/debug.h"
49 #include "wine/exception.h"
50 #include "crypt32_private.h"
52 /* This is a bit arbitrary, but to set some limit: */
53 #define MAX_ENCODED_LEN 0x02000000
55 #define ASN_FLAGS_MASK 0xe0
56 #define ASN_TYPE_MASK 0x1f
58 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
59 WINE_DECLARE_DEBUG_CHANNEL(crypt);
61 struct GenericArray
63 DWORD cItems;
64 BYTE *rgItems;
67 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
68 DWORD, DWORD, void *, DWORD *);
69 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
70 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
72 /* Internal decoders don't do memory allocation or exception handling, and
73 * they report how many bytes they decoded.
75 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
76 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
78 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
79 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
80 DWORD *pcbDecoded);
81 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
82 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
83 DWORD *pcbDecoded);
84 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
85 * time, doesn't do memory allocation, and doesn't do exception handling.
87 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
88 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
89 DWORD *pcbDecoded);
90 /* Assumes algo->Parameters.pbData is set ahead of time. */
91 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
92 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
93 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
94 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
97 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
98 DWORD *pcbDecoded);
99 /* Doesn't check the tag, assumes the caller does so */
100 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
101 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
102 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
103 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
104 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
105 * member has been initialized, doesn't do exception handling, and doesn't do
106 * memory allocation. Also doesn't check tag, assumes the caller has checked
107 * it.
109 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
110 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
111 DWORD *pcbDecoded);
112 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
113 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
114 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
115 DWORD *pcbDecoded);
116 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
117 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
118 DWORD *pcbDecoded);
120 /* Gets the number of length bytes from the given (leading) length byte */
121 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
123 /* Helper function to get the encoded length of the data starting at pbEncoded,
124 * where pbEncoded[0] is the tag. If the data are too short to contain a
125 * length or if the length is too large for cbEncoded, sets an appropriate
126 * error code and returns FALSE. If the encoded length is unknown due to
127 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
129 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
130 DWORD *len)
132 BOOL ret;
134 if (cbEncoded <= 1)
136 SetLastError(CRYPT_E_ASN1_CORRUPT);
137 ret = FALSE;
139 else if (pbEncoded[1] <= 0x7f)
141 if (pbEncoded[1] + 1 > cbEncoded)
143 SetLastError(CRYPT_E_ASN1_EOD);
144 ret = FALSE;
146 else
148 *len = pbEncoded[1];
149 ret = TRUE;
152 else if (pbEncoded[1] == 0x80)
154 *len = CMSG_INDEFINITE_LENGTH;
155 ret = TRUE;
157 else
159 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
161 if (lenLen > sizeof(DWORD) + 1)
163 SetLastError(CRYPT_E_ASN1_LARGE);
164 ret = FALSE;
166 else if (lenLen + 2 > cbEncoded)
168 SetLastError(CRYPT_E_ASN1_CORRUPT);
169 ret = FALSE;
171 else
173 DWORD out = 0;
175 pbEncoded += 2;
176 while (--lenLen)
178 out <<= 8;
179 out |= *pbEncoded++;
181 if (out + lenLen + 1 > cbEncoded)
183 SetLastError(CRYPT_E_ASN1_EOD);
184 ret = FALSE;
186 else
188 *len = out;
189 ret = TRUE;
193 return ret;
196 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
197 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
199 BOOL ret;
201 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
202 *len == CMSG_INDEFINITE_LENGTH)
204 SetLastError(CRYPT_E_ASN1_CORRUPT);
205 ret = FALSE;
207 return ret;
210 /* Helper function to check *pcbStructInfo, set it to the required size, and
211 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
212 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
213 * pointer to the newly allocated memory.
215 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
216 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
217 DWORD bytesNeeded)
219 BOOL ret = TRUE;
221 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
223 if (pDecodePara && pDecodePara->pfnAlloc)
224 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
225 else
226 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
227 if (!*(BYTE **)pvStructInfo)
228 ret = FALSE;
229 else
230 *pcbStructInfo = bytesNeeded;
232 else if (*pcbStructInfo < bytesNeeded)
234 *pcbStructInfo = bytesNeeded;
235 SetLastError(ERROR_MORE_DATA);
236 ret = FALSE;
238 else
239 *pcbStructInfo = bytesNeeded;
240 return ret;
243 static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
245 if (pDecodePara && pDecodePara->pfnFree)
246 pDecodePara->pfnFree(pv);
247 else
248 LocalFree(pv);
251 /* Helper function to check *pcbStructInfo and set it to the required size.
252 * Assumes pvStructInfo is not NULL.
254 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
256 BOOL ret;
258 if (*pcbStructInfo < bytesNeeded)
260 *pcbStructInfo = bytesNeeded;
261 SetLastError(ERROR_MORE_DATA);
262 ret = FALSE;
264 else
266 *pcbStructInfo = bytesNeeded;
267 ret = TRUE;
269 return ret;
272 /* tag:
273 * The expected tag of the item. If tag is 0, decodeFunc is called
274 * regardless of the tag value seen.
275 * offset:
276 * A sequence is decoded into a struct. The offset member is the
277 * offset of this item within that struct.
278 * decodeFunc:
279 * The decoder function to use. If this is NULL, then the member isn't
280 * decoded, but minSize space is reserved for it.
281 * minSize:
282 * The minimum amount of space occupied after decoding. You must set this.
283 * optional:
284 * If true, and the tag doesn't match the expected tag for this item,
285 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
286 * filled with 0 for this member.
287 * hasPointer, pointerOffset:
288 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
289 * the offset within the struct of the data pointer (or to the
290 * first data pointer, if more than one exist).
291 * size:
292 * Used by CRYPT_AsnDecodeSequence, not for your use.
294 struct AsnDecodeSequenceItem
296 BYTE tag;
297 DWORD offset;
298 InternalDecodeFunc decodeFunc;
299 DWORD minSize;
300 BOOL optional;
301 BOOL hasPointer;
302 DWORD pointerOffset;
303 DWORD size;
306 /* Decodes the items in a sequence, where the items are described in items,
307 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
308 * pvStructInfo. nextData is a pointer to the memory location at which the
309 * first decoded item with a dynamic pointer should point.
310 * Upon decoding, *cbDecoded is the total number of bytes decoded.
311 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
313 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
314 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
315 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
317 BOOL ret;
318 DWORD i, decoded = 0;
319 const BYTE *ptr = pbEncoded;
321 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
322 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
324 for (i = 0, ret = TRUE; ret && i < cItem; i++)
326 if (cbEncoded - (ptr - pbEncoded) != 0)
328 DWORD itemLen;
330 if ((ret = CRYPT_GetLengthIndefinite(ptr,
331 cbEncoded - (ptr - pbEncoded), &itemLen)))
333 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
335 if (ptr[0] == items[i].tag || !items[i].tag)
337 DWORD itemEncodedLen;
339 if (itemLen == CMSG_INDEFINITE_LENGTH)
340 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
341 else
342 itemEncodedLen = 1 + itemLenBytes + itemLen;
343 if (nextData && pvStructInfo && items[i].hasPointer)
345 TRACE("Setting next pointer to %p\n",
346 nextData);
347 *(BYTE **)((BYTE *)pvStructInfo +
348 items[i].pointerOffset) = nextData;
350 if (items[i].decodeFunc)
352 DWORD itemDecoded;
354 if (pvStructInfo)
355 TRACE("decoding item %d\n", i);
356 else
357 TRACE("sizing item %d\n", i);
358 ret = items[i].decodeFunc(ptr, itemEncodedLen,
359 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
360 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
361 : NULL, &items[i].size, &itemDecoded);
362 if (ret)
364 /* Account for alignment padding */
365 if (items[i].size % sizeof(DWORD_PTR))
366 items[i].size += sizeof(DWORD_PTR) -
367 items[i].size % sizeof(DWORD_PTR);
368 TRACE("item %d size: %d\n", i, items[i].size);
369 if (nextData && items[i].hasPointer &&
370 items[i].size > items[i].minSize)
371 nextData += items[i].size - items[i].minSize;
372 if (itemDecoded > itemEncodedLen)
374 WARN("decoded length %d exceeds encoded %d\n",
375 itemDecoded, itemEncodedLen);
376 SetLastError(CRYPT_E_ASN1_CORRUPT);
377 ret = FALSE;
379 else
381 if (itemLen == CMSG_INDEFINITE_LENGTH)
383 if (itemDecoded > itemEncodedLen - 2 ||
384 *(ptr + itemDecoded) != 0 ||
385 *(ptr + itemDecoded + 1) != 0)
387 TRACE("expected 0 TLV\n");
388 SetLastError(CRYPT_E_ASN1_CORRUPT);
389 ret = FALSE;
391 else
392 itemDecoded += 2;
394 if (ret)
396 ptr += itemDecoded;
397 decoded += itemDecoded;
398 TRACE("item %d: decoded %d bytes\n", i,
399 itemDecoded);
403 else if (items[i].optional &&
404 GetLastError() == CRYPT_E_ASN1_BADTAG)
406 TRACE("skipping optional item %d\n", i);
407 items[i].size = items[i].minSize;
408 SetLastError(NOERROR);
409 ret = TRUE;
411 else
412 TRACE("item %d failed: %08x\n", i,
413 GetLastError());
415 else if (itemLen == CMSG_INDEFINITE_LENGTH)
417 ERR("can't use indefinite length encoding without a decoder\n");
418 SetLastError(CRYPT_E_ASN1_CORRUPT);
419 ret = FALSE;
421 else
423 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
424 ptr += itemEncodedLen;
425 decoded += itemEncodedLen;
426 items[i].size = items[i].minSize;
429 else if (items[i].optional)
431 TRACE("skipping optional item %d\n", i);
432 items[i].size = items[i].minSize;
434 else
436 TRACE("item %d: tag %02x doesn't match expected %02x\n",
437 i, ptr[0], items[i].tag);
438 SetLastError(CRYPT_E_ASN1_BADTAG);
439 ret = FALSE;
443 else if (items[i].optional)
445 TRACE("missing optional item %d, skipping\n", i);
446 items[i].size = items[i].minSize;
448 else
450 TRACE("not enough bytes for item %d, failing\n", i);
451 SetLastError(CRYPT_E_ASN1_CORRUPT);
452 ret = FALSE;
455 if (cbDecoded)
456 *cbDecoded = decoded;
457 TRACE("returning %d\n", ret);
458 return ret;
461 /* This decodes an arbitrary sequence into a contiguous block of memory
462 * (basically, a struct.) Each element being decoded is described by a struct
463 * AsnDecodeSequenceItem, see above.
464 * startingPointer is an optional pointer to the first place where dynamic
465 * data will be stored. If you know the starting offset, you may pass it
466 * here. Otherwise, pass NULL, and one will be inferred from the items.
468 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
469 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
470 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
471 DWORD *pcbDecoded, void *startingPointer)
473 BOOL ret;
475 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
476 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
477 startingPointer);
479 if (!cbEncoded)
481 SetLastError(CRYPT_E_ASN1_EOD);
482 return FALSE;
484 if (pbEncoded[0] == ASN_SEQUENCE)
486 DWORD dataLen;
488 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
490 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
491 const BYTE *ptr = pbEncoded + 1 + lenBytes;
492 BOOL indefinite = FALSE;
494 cbEncoded -= 1 + lenBytes;
495 if (dataLen == CMSG_INDEFINITE_LENGTH)
497 dataLen = cbEncoded;
498 indefinite = TRUE;
500 else if (cbEncoded < dataLen)
502 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
503 cbEncoded);
504 SetLastError(CRYPT_E_ASN1_CORRUPT);
505 ret = FALSE;
507 if (ret)
509 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
510 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
511 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
513 if (cbDecoded > cbEncoded - 2)
515 /* Not enough space for 0 TLV */
516 SetLastError(CRYPT_E_ASN1_CORRUPT);
517 ret = FALSE;
519 else if (*(ptr + cbDecoded) != 0 ||
520 *(ptr + cbDecoded + 1) != 0)
522 TRACE("expected 0 TLV\n");
523 SetLastError(CRYPT_E_ASN1_CORRUPT);
524 ret = FALSE;
526 else
527 cbDecoded += 2;
530 if (ret && !indefinite && cbDecoded != dataLen)
532 TRACE("expected %d decoded, got %d, failing\n", dataLen,
533 cbDecoded);
534 SetLastError(CRYPT_E_ASN1_CORRUPT);
535 ret = FALSE;
537 if (ret)
539 DWORD i, bytesNeeded = 0, structSize = 0;
541 for (i = 0; i < cItem; i++)
543 bytesNeeded += items[i].size;
544 structSize += items[i].minSize;
546 if (pcbDecoded)
547 *pcbDecoded = 1 + lenBytes + cbDecoded;
548 if (!pvStructInfo)
549 *pcbStructInfo = bytesNeeded;
550 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
551 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
553 BYTE *nextData;
555 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
556 pvStructInfo = *(BYTE **)pvStructInfo;
557 if (startingPointer)
558 nextData = (BYTE *)startingPointer;
559 else
560 nextData = (BYTE *)pvStructInfo + structSize;
561 memset(pvStructInfo, 0, structSize);
562 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
563 ptr, dataLen, dwFlags, pvStructInfo, nextData,
564 &cbDecoded);
565 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
566 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
571 else
573 SetLastError(CRYPT_E_ASN1_BADTAG);
574 ret = FALSE;
576 TRACE("returning %d (%08x)\n", ret, GetLastError());
577 return ret;
580 /* tag:
581 * The expected tag of the entire encoded array (usually a variant
582 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
583 * regardless of the tag seen.
584 * decodeFunc:
585 * used to decode each item in the array
586 * itemSize:
587 * is the minimum size of each decoded item
588 * hasPointer:
589 * indicates whether each item has a dynamic pointer
590 * pointerOffset:
591 * indicates the offset within itemSize at which the pointer exists
593 struct AsnArrayDescriptor
595 BYTE tag;
596 InternalDecodeFunc decodeFunc;
597 DWORD itemSize;
598 BOOL hasPointer;
599 DWORD pointerOffset;
602 struct AsnArrayItemSize
604 DWORD encodedLen;
605 DWORD size;
608 /* Decodes an array of like types into a struct GenericArray.
609 * The layout and decoding of the array are described by a struct
610 * AsnArrayDescriptor.
612 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
613 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
614 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
615 DWORD *pcbDecoded, void *startingPointer)
617 BOOL ret = TRUE;
619 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
620 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
621 startingPointer);
623 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
625 DWORD dataLen;
627 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
629 DWORD bytesNeeded, cItems = 0, decoded;
630 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
631 /* There can be arbitrarily many items, but there is often only one.
633 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
635 decoded = 1 + lenBytes;
636 bytesNeeded = sizeof(struct GenericArray);
637 if (dataLen)
639 const BYTE *ptr;
640 BOOL doneDecoding = FALSE;
642 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
644 if (dataLen == CMSG_INDEFINITE_LENGTH)
646 if (ptr[0] == 0)
648 doneDecoding = TRUE;
649 if (ptr[1] != 0)
651 SetLastError(CRYPT_E_ASN1_CORRUPT);
652 ret = FALSE;
654 else
655 decoded += 2;
658 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
659 doneDecoding = TRUE;
660 if (!doneDecoding)
662 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
664 /* Each item decoded may not tolerate extraneous bytes,
665 * so get the length of the next element if known.
667 if ((ret = CRYPT_GetLengthIndefinite(ptr,
668 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
670 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
671 itemEncoded = cbEncoded - (ptr - pbEncoded);
672 else
673 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
674 itemDataLen;
676 if (ret)
677 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
678 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
679 &itemDecoded);
680 if (ret)
682 cItems++;
683 if (itemSizes != &itemSize)
684 itemSizes = CryptMemRealloc(itemSizes,
685 cItems * sizeof(struct AsnArrayItemSize));
686 else if (cItems > 1)
688 itemSizes =
689 CryptMemAlloc(
690 cItems * sizeof(struct AsnArrayItemSize));
691 if (itemSizes)
692 memcpy(itemSizes, &itemSize,
693 sizeof(itemSize));
695 if (itemSizes)
697 decoded += itemDecoded;
698 itemSizes[cItems - 1].encodedLen = itemEncoded;
699 itemSizes[cItems - 1].size = size;
700 bytesNeeded += size;
701 ptr += itemEncoded;
703 else
704 ret = FALSE;
709 if (ret)
711 if (pcbDecoded)
712 *pcbDecoded = decoded;
713 if (!pvStructInfo)
714 *pcbStructInfo = bytesNeeded;
715 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
716 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
718 DWORD i;
719 BYTE *nextData;
720 const BYTE *ptr;
721 struct GenericArray *array;
723 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
724 pvStructInfo = *(BYTE **)pvStructInfo;
725 array = (struct GenericArray *)pvStructInfo;
726 array->cItems = cItems;
727 if (startingPointer)
728 array->rgItems = startingPointer;
729 else
730 array->rgItems = (BYTE *)array +
731 sizeof(struct GenericArray);
732 nextData = array->rgItems +
733 array->cItems * arrayDesc->itemSize;
734 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
735 i < cItems && ptr - pbEncoded - 1 - lenBytes <
736 dataLen; i++)
738 DWORD itemDecoded;
740 if (arrayDesc->hasPointer)
741 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
742 + arrayDesc->pointerOffset) = nextData;
743 ret = arrayDesc->decodeFunc(ptr,
744 itemSizes[i].encodedLen,
745 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
746 array->rgItems + i * arrayDesc->itemSize,
747 &itemSizes[i].size, &itemDecoded);
748 if (ret)
750 nextData += itemSizes[i].size - arrayDesc->itemSize;
751 ptr += itemDecoded;
754 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
755 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
758 if (itemSizes != &itemSize)
759 CryptMemFree(itemSizes);
762 else
764 SetLastError(CRYPT_E_ASN1_BADTAG);
765 ret = FALSE;
767 return ret;
770 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
771 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
772 * to CRYPT_E_ASN1_CORRUPT.
773 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
774 * set!
776 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
777 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
779 BOOL ret;
780 DWORD dataLen;
782 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
784 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
785 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
787 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
788 bytesNeeded += 1 + lenBytes + dataLen;
790 if (pcbDecoded)
791 *pcbDecoded = 1 + lenBytes + dataLen;
792 if (!pvStructInfo)
793 *pcbStructInfo = bytesNeeded;
794 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
796 CRYPT_DER_BLOB *blob;
798 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
799 pvStructInfo = *(BYTE **)pvStructInfo;
800 blob = (CRYPT_DER_BLOB *)pvStructInfo;
801 blob->cbData = 1 + lenBytes + dataLen;
802 if (blob->cbData)
804 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
805 blob->pbData = (BYTE *)pbEncoded;
806 else
808 assert(blob->pbData);
809 memcpy(blob->pbData, pbEncoded, blob->cbData);
812 else
814 SetLastError(CRYPT_E_ASN1_CORRUPT);
815 ret = FALSE;
819 return ret;
822 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
823 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
824 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
825 DWORD *pcbDecoded)
827 BOOL ret;
829 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
830 pvStructInfo, *pcbStructInfo, pcbDecoded);
832 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
833 * place.
835 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
836 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
837 pcbDecoded);
838 if (ret && pvStructInfo)
840 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
842 if (blob->cbData)
844 DWORD i;
845 BYTE temp;
847 for (i = 0; i < blob->cbData / 2; i++)
849 temp = blob->pbData[i];
850 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
851 blob->pbData[blob->cbData - i - 1] = temp;
855 TRACE("returning %d (%08x)\n", ret, GetLastError());
856 return ret;
859 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
860 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
861 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
863 BOOL ret = TRUE;
865 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
866 pDecodePara, pvStructInfo, *pcbStructInfo);
868 __TRY
870 struct AsnDecodeSequenceItem items[] = {
871 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
872 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
873 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
874 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
875 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
876 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
877 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
878 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
879 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
880 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
883 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
884 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
885 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
886 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
887 pcbStructInfo, NULL, NULL);
889 __EXCEPT_PAGE_FAULT
891 SetLastError(STATUS_ACCESS_VIOLATION);
892 ret = FALSE;
894 __ENDTRY
896 TRACE("Returning %d (%08x)\n", ret, GetLastError());
897 return ret;
900 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
901 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
903 BOOL ret;
904 DWORD dataLen;
906 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
908 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
910 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
911 dwFlags, pvStructInfo, pcbStructInfo, NULL);
912 if (pcbDecoded)
913 *pcbDecoded = 1 + lenBytes + dataLen;
915 return ret;
918 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
919 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
921 BOOL ret;
923 struct AsnDecodeSequenceItem items[] = {
924 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
925 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
926 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
927 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
930 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
931 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
932 pcbDecoded, NULL);
933 return ret;
936 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
937 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
938 DWORD *pcbDecoded)
940 BOOL ret;
941 DWORD dataLen;
943 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
945 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
947 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
948 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
949 if (ret && pcbDecoded)
950 *pcbDecoded = 1 + lenBytes + dataLen;
952 return ret;
955 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
956 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
957 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
959 BOOL ret = TRUE;
960 struct AsnDecodeSequenceItem items[] = {
961 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
962 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
963 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
964 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
965 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
966 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
967 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
968 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
969 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
970 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
971 Issuer.pbData) },
972 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
973 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
974 FALSE, 0 },
975 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
976 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
977 Subject.pbData) },
978 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
979 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
980 FALSE, TRUE, offsetof(CERT_INFO,
981 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
982 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
983 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
984 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
985 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
986 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
987 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
988 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
989 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
990 offsetof(CERT_INFO, rgExtension), 0 },
993 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
994 pDecodePara, pvStructInfo, *pcbStructInfo);
996 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
997 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
998 NULL, NULL);
999 if (ret && pvStructInfo)
1001 CERT_INFO *info;
1003 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1004 info = *(CERT_INFO **)pvStructInfo;
1005 else
1006 info = (CERT_INFO *)pvStructInfo;
1007 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1008 !info->Subject.cbData)
1010 SetLastError(CRYPT_E_ASN1_CORRUPT);
1011 /* Don't need to deallocate, because it should have failed on the
1012 * first pass (and no memory was allocated.)
1014 ret = FALSE;
1018 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1019 return ret;
1022 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1023 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1024 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1026 BOOL ret = FALSE;
1028 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1029 pDecodePara, pvStructInfo, *pcbStructInfo);
1031 __TRY
1033 DWORD size = 0;
1035 /* Unless told not to, first try to decode it as a signed cert. */
1036 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1038 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1040 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1041 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1042 (BYTE *)&signedCert, &size);
1043 if (ret)
1045 size = 0;
1046 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1047 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1048 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1049 pvStructInfo, pcbStructInfo);
1050 LocalFree(signedCert);
1053 /* Failing that, try it as an unsigned cert */
1054 if (!ret)
1056 size = 0;
1057 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1058 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1059 pDecodePara, pvStructInfo, pcbStructInfo);
1062 __EXCEPT_PAGE_FAULT
1064 SetLastError(STATUS_ACCESS_VIOLATION);
1066 __ENDTRY
1068 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1069 return ret;
1072 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1073 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1075 BOOL ret;
1076 struct AsnDecodeSequenceItem items[] = {
1077 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1078 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1079 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1080 { 0, offsetof(CRL_ENTRY, RevocationDate),
1081 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1082 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1083 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1084 offsetof(CRL_ENTRY, rgExtension), 0 },
1086 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1088 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1089 *pcbStructInfo);
1091 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1092 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1093 entry ? entry->SerialNumber.pbData : NULL);
1094 if (ret && entry && !entry->SerialNumber.cbData)
1096 WARN("empty CRL entry serial number\n");
1097 SetLastError(CRYPT_E_ASN1_CORRUPT);
1098 ret = FALSE;
1100 return ret;
1103 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1104 * been set prior to calling.
1106 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1107 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1109 BOOL ret;
1110 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1111 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1112 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1113 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1115 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1116 pvStructInfo, *pcbStructInfo, pcbDecoded);
1118 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1119 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1120 entries ? entries->rgItems : NULL);
1121 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1122 return ret;
1125 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1126 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1127 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1129 struct AsnDecodeSequenceItem items[] = {
1130 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1131 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1132 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1133 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1134 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1135 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1136 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1137 Issuer.pbData) },
1138 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1139 sizeof(FILETIME), FALSE, FALSE, 0 },
1140 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1141 sizeof(FILETIME), TRUE, FALSE, 0 },
1142 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1143 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1144 offsetof(CRL_INFO, rgCRLEntry), 0 },
1145 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1146 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1147 offsetof(CRL_INFO, rgExtension), 0 },
1149 BOOL ret = TRUE;
1151 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1152 pDecodePara, pvStructInfo, *pcbStructInfo);
1154 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1155 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1156 NULL, NULL);
1158 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1159 return ret;
1162 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1163 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1164 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1166 BOOL ret = FALSE;
1168 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1169 pDecodePara, pvStructInfo, *pcbStructInfo);
1171 __TRY
1173 DWORD size = 0;
1175 /* Unless told not to, first try to decode it as a signed crl. */
1176 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1178 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1180 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1181 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1182 (BYTE *)&signedCrl, &size);
1183 if (ret)
1185 size = 0;
1186 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1187 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1188 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1189 pvStructInfo, pcbStructInfo);
1190 LocalFree(signedCrl);
1193 /* Failing that, try it as an unsigned crl */
1194 if (!ret)
1196 size = 0;
1197 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1198 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1199 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1202 __EXCEPT_PAGE_FAULT
1204 SetLastError(STATUS_ACCESS_VIOLATION);
1206 __ENDTRY
1208 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1209 return ret;
1212 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1213 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1215 BOOL ret = TRUE;
1216 DWORD dataLen;
1218 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1219 pvStructInfo, *pcbStructInfo);
1221 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1223 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1224 DWORD bytesNeeded = sizeof(LPSTR);
1226 if (dataLen)
1228 /* The largest possible string for the first two components
1229 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1231 char firstTwo[6];
1232 const BYTE *ptr;
1234 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1235 pbEncoded[1 + lenBytes] / 40,
1236 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1237 * 40);
1238 bytesNeeded += strlen(firstTwo) + 1;
1239 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1240 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1242 /* large enough for ".4000000" */
1243 char str[9];
1244 int val = 0;
1246 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1247 (*ptr & 0x80))
1249 val <<= 7;
1250 val |= *ptr & 0x7f;
1251 ptr++;
1253 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1254 (*ptr & 0x80))
1256 SetLastError(CRYPT_E_ASN1_CORRUPT);
1257 ret = FALSE;
1259 else
1261 val <<= 7;
1262 val |= *ptr++;
1263 snprintf(str, sizeof(str), ".%d", val);
1264 bytesNeeded += strlen(str);
1268 if (pcbDecoded)
1269 *pcbDecoded = 1 + lenBytes + dataLen;
1270 if (!pvStructInfo)
1271 *pcbStructInfo = bytesNeeded;
1272 else if (*pcbStructInfo < bytesNeeded)
1274 *pcbStructInfo = bytesNeeded;
1275 SetLastError(ERROR_MORE_DATA);
1276 ret = FALSE;
1278 else
1280 if (dataLen)
1282 const BYTE *ptr;
1283 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1285 *pszObjId = 0;
1286 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1287 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1288 40) * 40);
1289 pszObjId += strlen(pszObjId);
1290 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1291 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1293 int val = 0;
1295 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1296 (*ptr & 0x80))
1298 val <<= 7;
1299 val |= *ptr & 0x7f;
1300 ptr++;
1302 val <<= 7;
1303 val |= *ptr++;
1304 sprintf(pszObjId, ".%d", val);
1305 pszObjId += strlen(pszObjId);
1308 else
1309 *(LPSTR *)pvStructInfo = NULL;
1310 *pcbStructInfo = bytesNeeded;
1313 return ret;
1316 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1317 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1319 BOOL ret;
1321 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1322 pvStructInfo, *pcbStructInfo);
1324 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1325 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1326 pvStructInfo, pcbStructInfo, pcbDecoded);
1327 else
1329 SetLastError(CRYPT_E_ASN1_BADTAG);
1330 ret = FALSE;
1332 return ret;
1335 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1336 * ahead of time!
1338 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1339 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1341 struct AsnDecodeSequenceItem items[] = {
1342 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1343 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1344 offsetof(CERT_EXTENSION, pszObjId), 0 },
1345 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1346 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1347 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1348 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1349 offsetof(CERT_EXTENSION, Value.pbData) },
1351 BOOL ret = TRUE;
1352 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1354 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1355 *pcbStructInfo);
1357 if (ext)
1358 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1359 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1360 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1361 pcbDecoded, ext ? ext->pszObjId : NULL);
1362 if (ext)
1363 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1364 debugstr_a(ext->pszObjId));
1365 TRACE("returning %d (%08x)\n", ret, GetLastError());
1366 return ret;
1369 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1370 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1371 DWORD *pcbDecoded)
1373 BOOL ret = TRUE;
1374 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1375 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1376 offsetof(CERT_EXTENSION, pszObjId) };
1377 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1379 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1380 pvStructInfo, *pcbStructInfo, pcbDecoded);
1382 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1383 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1384 exts ? exts->rgExtension : NULL);
1385 return ret;
1388 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1389 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1390 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1392 BOOL ret = TRUE;
1394 __TRY
1396 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1397 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1398 if (ret && pvStructInfo)
1400 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1401 pcbStructInfo, *pcbStructInfo);
1402 if (ret)
1404 CERT_EXTENSIONS *exts;
1406 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1407 pvStructInfo = *(BYTE **)pvStructInfo;
1408 exts = (CERT_EXTENSIONS *)pvStructInfo;
1409 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1410 sizeof(CERT_EXTENSIONS));
1411 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1412 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1413 pcbStructInfo, NULL);
1417 __EXCEPT_PAGE_FAULT
1419 SetLastError(STATUS_ACCESS_VIOLATION);
1420 ret = FALSE;
1422 __ENDTRY
1423 return ret;
1426 /* Warning: this assumes the address of value->Value.pbData is already set, in
1427 * order to avoid overwriting memory. (In some cases, it may change it, if it
1428 * doesn't copy anything to memory.) Be sure to set it correctly!
1430 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1431 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1432 DWORD *pcbDecoded)
1434 BOOL ret = TRUE;
1435 DWORD dataLen;
1436 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1438 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1440 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1441 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1443 switch (pbEncoded[0])
1445 case ASN_OCTETSTRING:
1446 valueType = CERT_RDN_OCTET_STRING;
1447 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1448 bytesNeeded += dataLen;
1449 break;
1450 case ASN_NUMERICSTRING:
1451 valueType = CERT_RDN_NUMERIC_STRING;
1452 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1453 bytesNeeded += dataLen;
1454 break;
1455 case ASN_PRINTABLESTRING:
1456 valueType = CERT_RDN_PRINTABLE_STRING;
1457 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1458 bytesNeeded += dataLen;
1459 break;
1460 case ASN_IA5STRING:
1461 valueType = CERT_RDN_IA5_STRING;
1462 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1463 bytesNeeded += dataLen;
1464 break;
1465 case ASN_T61STRING:
1466 valueType = CERT_RDN_T61_STRING;
1467 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1468 bytesNeeded += dataLen;
1469 break;
1470 case ASN_VIDEOTEXSTRING:
1471 valueType = CERT_RDN_VIDEOTEX_STRING;
1472 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1473 bytesNeeded += dataLen;
1474 break;
1475 case ASN_GRAPHICSTRING:
1476 valueType = CERT_RDN_GRAPHIC_STRING;
1477 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1478 bytesNeeded += dataLen;
1479 break;
1480 case ASN_VISIBLESTRING:
1481 valueType = CERT_RDN_VISIBLE_STRING;
1482 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1483 bytesNeeded += dataLen;
1484 break;
1485 case ASN_GENERALSTRING:
1486 valueType = CERT_RDN_GENERAL_STRING;
1487 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1488 bytesNeeded += dataLen;
1489 break;
1490 case ASN_UNIVERSALSTRING:
1491 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1492 SetLastError(CRYPT_E_ASN1_BADTAG);
1493 return FALSE;
1494 case ASN_BMPSTRING:
1495 valueType = CERT_RDN_BMP_STRING;
1496 bytesNeeded += dataLen;
1497 break;
1498 case ASN_UTF8STRING:
1499 valueType = CERT_RDN_UTF8_STRING;
1500 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1501 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1502 break;
1503 default:
1504 SetLastError(CRYPT_E_ASN1_BADTAG);
1505 return FALSE;
1508 if (pcbDecoded)
1509 *pcbDecoded = 1 + lenBytes + dataLen;
1510 if (!value)
1511 *pcbStructInfo = bytesNeeded;
1512 else if (*pcbStructInfo < bytesNeeded)
1514 *pcbStructInfo = bytesNeeded;
1515 SetLastError(ERROR_MORE_DATA);
1516 ret = FALSE;
1518 else
1520 *pcbStructInfo = bytesNeeded;
1521 value->dwValueType = valueType;
1522 if (dataLen)
1524 DWORD i;
1526 assert(value->Value.pbData);
1527 switch (pbEncoded[0])
1529 case ASN_OCTETSTRING:
1530 case ASN_NUMERICSTRING:
1531 case ASN_PRINTABLESTRING:
1532 case ASN_IA5STRING:
1533 case ASN_T61STRING:
1534 case ASN_VIDEOTEXSTRING:
1535 case ASN_GRAPHICSTRING:
1536 case ASN_VISIBLESTRING:
1537 case ASN_GENERALSTRING:
1538 value->Value.cbData = dataLen;
1539 if (dataLen)
1541 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1542 memcpy(value->Value.pbData,
1543 pbEncoded + 1 + lenBytes, dataLen);
1544 else
1545 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1546 lenBytes;
1548 break;
1549 case ASN_BMPSTRING:
1551 LPWSTR str = (LPWSTR)value->Value.pbData;
1553 value->Value.cbData = dataLen;
1554 for (i = 0; i < dataLen / 2; i++)
1555 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1556 pbEncoded[1 + lenBytes + 2 * i + 1];
1557 break;
1559 case ASN_UTF8STRING:
1561 LPWSTR str = (LPWSTR)value->Value.pbData;
1563 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1564 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1565 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1566 break;
1570 else
1572 value->Value.cbData = 0;
1573 value->Value.pbData = NULL;
1577 return ret;
1580 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1581 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1582 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1584 BOOL ret = TRUE;
1586 __TRY
1588 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1589 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1590 if (ret && pvStructInfo)
1592 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1593 pcbStructInfo, *pcbStructInfo);
1594 if (ret)
1596 CERT_NAME_VALUE *value;
1598 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1599 pvStructInfo = *(BYTE **)pvStructInfo;
1600 value = (CERT_NAME_VALUE *)pvStructInfo;
1601 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1602 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1603 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1604 pcbStructInfo, NULL);
1608 __EXCEPT_PAGE_FAULT
1610 SetLastError(STATUS_ACCESS_VIOLATION);
1611 ret = FALSE;
1613 __ENDTRY
1614 return ret;
1617 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1618 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1619 DWORD *pcbDecoded)
1621 BOOL ret = TRUE;
1622 DWORD dataLen;
1623 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1625 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1627 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1628 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1630 switch (pbEncoded[0])
1632 case ASN_NUMERICSTRING:
1633 valueType = CERT_RDN_NUMERIC_STRING;
1634 bytesNeeded += dataLen * 2;
1635 break;
1636 case ASN_PRINTABLESTRING:
1637 valueType = CERT_RDN_PRINTABLE_STRING;
1638 bytesNeeded += dataLen * 2;
1639 break;
1640 case ASN_IA5STRING:
1641 valueType = CERT_RDN_IA5_STRING;
1642 bytesNeeded += dataLen * 2;
1643 break;
1644 case ASN_T61STRING:
1645 valueType = CERT_RDN_T61_STRING;
1646 bytesNeeded += dataLen * 2;
1647 break;
1648 case ASN_VIDEOTEXSTRING:
1649 valueType = CERT_RDN_VIDEOTEX_STRING;
1650 bytesNeeded += dataLen * 2;
1651 break;
1652 case ASN_GRAPHICSTRING:
1653 valueType = CERT_RDN_GRAPHIC_STRING;
1654 bytesNeeded += dataLen * 2;
1655 break;
1656 case ASN_VISIBLESTRING:
1657 valueType = CERT_RDN_VISIBLE_STRING;
1658 bytesNeeded += dataLen * 2;
1659 break;
1660 case ASN_GENERALSTRING:
1661 valueType = CERT_RDN_GENERAL_STRING;
1662 bytesNeeded += dataLen * 2;
1663 break;
1664 case ASN_UNIVERSALSTRING:
1665 valueType = CERT_RDN_UNIVERSAL_STRING;
1666 bytesNeeded += dataLen / 2;
1667 break;
1668 case ASN_BMPSTRING:
1669 valueType = CERT_RDN_BMP_STRING;
1670 bytesNeeded += dataLen;
1671 break;
1672 case ASN_UTF8STRING:
1673 valueType = CERT_RDN_UTF8_STRING;
1674 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1675 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1676 break;
1677 default:
1678 SetLastError(CRYPT_E_ASN1_BADTAG);
1679 return FALSE;
1682 if (pcbDecoded)
1683 *pcbDecoded = 1 + lenBytes + dataLen;
1684 if (!value)
1685 *pcbStructInfo = bytesNeeded;
1686 else if (*pcbStructInfo < bytesNeeded)
1688 *pcbStructInfo = bytesNeeded;
1689 SetLastError(ERROR_MORE_DATA);
1690 ret = FALSE;
1692 else
1694 *pcbStructInfo = bytesNeeded;
1695 value->dwValueType = valueType;
1696 if (dataLen)
1698 DWORD i;
1699 LPWSTR str = (LPWSTR)value->Value.pbData;
1701 assert(value->Value.pbData);
1702 switch (pbEncoded[0])
1704 case ASN_NUMERICSTRING:
1705 case ASN_PRINTABLESTRING:
1706 case ASN_IA5STRING:
1707 case ASN_T61STRING:
1708 case ASN_VIDEOTEXSTRING:
1709 case ASN_GRAPHICSTRING:
1710 case ASN_VISIBLESTRING:
1711 case ASN_GENERALSTRING:
1712 value->Value.cbData = dataLen * 2;
1713 for (i = 0; i < dataLen; i++)
1714 str[i] = pbEncoded[1 + lenBytes + i];
1715 break;
1716 case ASN_UNIVERSALSTRING:
1717 value->Value.cbData = dataLen / 2;
1718 for (i = 0; i < dataLen / 4; i++)
1719 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1720 | pbEncoded[1 + lenBytes + 2 * i + 3];
1721 break;
1722 case ASN_BMPSTRING:
1723 value->Value.cbData = dataLen;
1724 for (i = 0; i < dataLen / 2; i++)
1725 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1726 pbEncoded[1 + lenBytes + 2 * i + 1];
1727 break;
1728 case ASN_UTF8STRING:
1729 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1730 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1731 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1732 break;
1735 else
1737 value->Value.cbData = 0;
1738 value->Value.pbData = NULL;
1742 return ret;
1745 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1746 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1747 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1749 BOOL ret = TRUE;
1751 __TRY
1753 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1754 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1755 if (ret && pvStructInfo)
1757 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1758 pcbStructInfo, *pcbStructInfo);
1759 if (ret)
1761 CERT_NAME_VALUE *value;
1763 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1764 pvStructInfo = *(BYTE **)pvStructInfo;
1765 value = (CERT_NAME_VALUE *)pvStructInfo;
1766 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1767 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1768 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1769 pcbStructInfo, NULL);
1773 __EXCEPT_PAGE_FAULT
1775 SetLastError(STATUS_ACCESS_VIOLATION);
1776 ret = FALSE;
1778 __ENDTRY
1779 return ret;
1782 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1783 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1785 BOOL ret;
1786 struct AsnDecodeSequenceItem items[] = {
1787 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1788 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1789 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1790 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1791 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1792 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1794 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1796 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1797 pvStructInfo, *pcbStructInfo);
1799 if (attr)
1800 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1801 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1802 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1803 attr ? attr->pszObjId : NULL);
1804 if (attr)
1806 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1807 debugstr_a(attr->pszObjId));
1808 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1810 TRACE("returning %d (%08x)\n", ret, GetLastError());
1811 return ret;
1814 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1815 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1817 BOOL ret = TRUE;
1818 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1819 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1820 offsetof(CERT_RDN_ATTR, pszObjId) };
1821 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1823 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1824 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1825 rdn ? rdn->rgRDNAttr : NULL);
1826 return ret;
1829 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1830 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1831 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1833 BOOL ret = TRUE;
1835 __TRY
1837 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1838 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1839 offsetof(CERT_RDN, rgRDNAttr) };
1841 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1842 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1844 __EXCEPT_PAGE_FAULT
1846 SetLastError(STATUS_ACCESS_VIOLATION);
1847 ret = FALSE;
1849 __ENDTRY
1850 return ret;
1853 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1854 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1855 DWORD *pcbDecoded)
1857 BOOL ret;
1858 struct AsnDecodeSequenceItem items[] = {
1859 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1860 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1861 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1862 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1863 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1864 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1866 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1868 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1869 pvStructInfo, *pcbStructInfo);
1871 if (attr)
1872 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1873 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1874 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1875 attr ? attr->pszObjId : NULL);
1876 if (attr)
1878 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1879 debugstr_a(attr->pszObjId));
1880 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1882 TRACE("returning %d (%08x)\n", ret, GetLastError());
1883 return ret;
1886 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1887 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1889 BOOL ret = TRUE;
1890 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1891 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1892 offsetof(CERT_RDN_ATTR, pszObjId) };
1893 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1895 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1896 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1897 rdn ? rdn->rgRDNAttr : NULL);
1898 return ret;
1901 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1902 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1903 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1905 BOOL ret = TRUE;
1907 __TRY
1909 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1910 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1911 offsetof(CERT_RDN, rgRDNAttr) };
1913 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1914 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1916 __EXCEPT_PAGE_FAULT
1918 SetLastError(STATUS_ACCESS_VIOLATION);
1919 ret = FALSE;
1921 __ENDTRY
1922 return ret;
1925 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1926 DWORD *pcbDecoded)
1928 BOOL ret = TRUE, done = FALSE;
1929 DWORD indefiniteNestingLevels = 0, decoded = 0;
1931 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1933 do {
1934 DWORD dataLen;
1936 if (!cbEncoded)
1937 done = TRUE;
1938 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
1939 &dataLen)))
1941 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1943 if (dataLen == CMSG_INDEFINITE_LENGTH)
1945 indefiniteNestingLevels++;
1946 pbEncoded += 1 + lenBytes;
1947 cbEncoded -= 1 + lenBytes;
1948 decoded += 1 + lenBytes;
1949 TRACE("indefiniteNestingLevels = %d\n",
1950 indefiniteNestingLevels);
1952 else
1954 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
1955 indefiniteNestingLevels)
1957 indefiniteNestingLevels--;
1958 TRACE("indefiniteNestingLevels = %d\n",
1959 indefiniteNestingLevels);
1961 pbEncoded += 1 + lenBytes + dataLen;
1962 cbEncoded -= 1 + lenBytes + dataLen;
1963 decoded += 1 + lenBytes + dataLen;
1964 if (!indefiniteNestingLevels)
1965 done = TRUE;
1968 } while (ret && !done);
1969 /* If we haven't found all 0 TLVs, we haven't found the end */
1970 if (ret && indefiniteNestingLevels)
1972 SetLastError(CRYPT_E_ASN1_EOD);
1973 ret = FALSE;
1975 if (ret)
1976 *pcbDecoded = decoded;
1977 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
1978 return ret;
1981 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1982 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1983 DWORD *pcbDecoded)
1985 BOOL ret = TRUE;
1986 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
1988 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1989 pvStructInfo, *pcbStructInfo);
1991 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
1993 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1994 bytesNeeded += encodedLen;
1995 if (!pvStructInfo)
1996 *pcbStructInfo = bytesNeeded;
1997 else if (*pcbStructInfo < bytesNeeded)
1999 SetLastError(ERROR_MORE_DATA);
2000 *pcbStructInfo = bytesNeeded;
2001 ret = FALSE;
2003 else
2005 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
2007 *pcbStructInfo = bytesNeeded;
2008 blob->cbData = encodedLen;
2009 if (encodedLen)
2011 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2012 blob->pbData = (LPBYTE)pbEncoded;
2013 else
2015 assert(blob->pbData);
2016 memcpy(blob->pbData, pbEncoded, blob->cbData);
2019 else
2020 blob->pbData = NULL;
2022 if (pcbDecoded)
2023 *pcbDecoded = encodedLen;
2025 return ret;
2028 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
2029 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2031 BOOL ret;
2032 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
2033 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2034 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
2036 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2037 pvStructInfo, *pcbStructInfo, pcbDecoded);
2039 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2040 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2041 array ? array->rgItems : NULL);
2042 return ret;
2045 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2046 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2048 BOOL ret;
2049 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2050 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2051 CTL_USAGE *usage = (CTL_USAGE *)pvStructInfo;
2053 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2054 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2055 usage ? usage->rgpszUsageIdentifier : NULL);
2056 return ret;
2059 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2060 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2062 struct AsnDecodeSequenceItem items[] = {
2063 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2064 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2065 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2066 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2067 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), FALSE,
2068 TRUE, offsetof(CTL_ENTRY, rgAttribute), 0 },
2070 BOOL ret = TRUE;
2071 CTL_ENTRY *entry = (CTL_ENTRY *)pvStructInfo;
2073 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2074 *pcbStructInfo);
2076 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2077 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2078 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2079 return ret;
2082 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2083 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2085 BOOL ret;
2086 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2087 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2088 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2089 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2091 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2092 pvStructInfo, *pcbStructInfo, pcbDecoded);
2094 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2095 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2096 entries ? entries->rgItems : NULL);
2097 return ret;
2100 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2101 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2102 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2104 BOOL ret = FALSE;
2106 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2107 pDecodePara, pvStructInfo, *pcbStructInfo);
2109 __TRY
2111 struct AsnDecodeSequenceItem items[] = {
2112 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2113 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2114 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2115 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2116 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2117 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2118 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
2119 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2120 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2121 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2122 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2123 { 0, offsetof(CTL_INFO, ThisUpdate),
2124 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2125 0 },
2126 { 0, offsetof(CTL_INFO, NextUpdate),
2127 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2128 0 },
2129 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2130 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2131 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2132 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2133 CRYPT_AsnDecodeCTLEntries, sizeof(struct GenericArray),
2134 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2135 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2136 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
2137 offsetof(CTL_INFO, rgExtension), 0 },
2140 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2141 pDecodePara, pvStructInfo, *pcbStructInfo);
2143 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2144 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2145 pcbStructInfo, NULL, NULL);
2147 __EXCEPT_PAGE_FAULT
2149 SetLastError(STATUS_ACCESS_VIOLATION);
2151 __ENDTRY
2152 return ret;
2155 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2156 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2157 DWORD *pcbDecoded)
2159 BOOL ret;
2160 struct AsnDecodeSequenceItem items[] = {
2161 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2162 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2163 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2164 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2165 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2166 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2168 PCRYPT_SMIME_CAPABILITY capability = (PCRYPT_SMIME_CAPABILITY)pvStructInfo;
2170 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2171 pvStructInfo, *pcbStructInfo);
2173 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2174 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2175 pcbDecoded, capability ? capability->pszObjId : NULL);
2176 TRACE("returning %d\n", ret);
2177 return ret;
2180 static BOOL CRYPT_AsnDecodeSMIMECapabilitiesInternal(const BYTE *pbEncoded,
2181 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2182 DWORD *pcbDecoded)
2184 struct AsnArrayDescriptor arrayDesc = { 0,
2185 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2186 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2187 PCRYPT_SMIME_CAPABILITIES capabilities =
2188 (PCRYPT_SMIME_CAPABILITIES)pvStructInfo;
2189 BOOL ret;
2191 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2192 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2193 capabilities ? capabilities->rgCapability : NULL);
2194 return ret;
2197 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2198 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2199 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2201 BOOL ret = FALSE;
2203 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2204 pDecodePara, pvStructInfo, *pcbStructInfo);
2206 __TRY
2208 DWORD bytesNeeded;
2210 if (!cbEncoded)
2211 SetLastError(CRYPT_E_ASN1_EOD);
2212 else if (pbEncoded[0] != ASN_SEQUENCEOF)
2213 SetLastError(CRYPT_E_ASN1_CORRUPT);
2214 else if ((ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
2215 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2216 NULL)))
2218 if (!pvStructInfo)
2219 *pcbStructInfo = bytesNeeded;
2220 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2221 pvStructInfo, pcbStructInfo, bytesNeeded)))
2223 PCRYPT_SMIME_CAPABILITIES capabilities;
2225 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2226 pvStructInfo = *(BYTE **)pvStructInfo;
2227 capabilities = (PCRYPT_SMIME_CAPABILITIES)pvStructInfo;
2228 capabilities->rgCapability =
2229 (PCRYPT_SMIME_CAPABILITY)((BYTE *)pvStructInfo +
2230 sizeof(CRYPT_SMIME_CAPABILITIES));
2231 ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
2232 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2233 &bytesNeeded, NULL);
2237 __EXCEPT_PAGE_FAULT
2239 SetLastError(STATUS_ACCESS_VIOLATION);
2241 __ENDTRY
2242 TRACE("returning %d\n", ret);
2243 return ret;
2246 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2247 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2248 DWORD *pcbDecoded)
2250 BOOL ret;
2251 struct AsnDecodeSequenceItem items[] = {
2252 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2253 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2254 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2255 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2256 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
2257 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2259 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2261 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2262 pvStructInfo, *pcbStructInfo);
2264 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2265 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2266 pcbDecoded, attr ? attr->pszObjId : NULL);
2267 TRACE("returning %d\n", ret);
2268 return ret;
2271 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2272 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2273 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2275 BOOL ret = FALSE;
2277 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2278 pDecodePara, pvStructInfo, *pcbStructInfo);
2280 __TRY
2282 DWORD bytesNeeded;
2284 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2285 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2286 if (ret)
2288 if (!pvStructInfo)
2289 *pcbStructInfo = bytesNeeded;
2290 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2291 pvStructInfo, pcbStructInfo, bytesNeeded)))
2293 PCRYPT_ATTRIBUTE attr;
2295 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2296 pvStructInfo = *(BYTE **)pvStructInfo;
2297 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2298 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2299 sizeof(CRYPT_ATTRIBUTE));
2300 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2301 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2302 NULL);
2306 __EXCEPT_PAGE_FAULT
2308 SetLastError(STATUS_ACCESS_VIOLATION);
2310 __ENDTRY
2311 TRACE("returning %d\n", ret);
2312 return ret;
2315 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2316 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2317 DWORD *pcbDecoded)
2319 struct AsnArrayDescriptor arrayDesc = { 0,
2320 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2321 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2322 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2323 BOOL ret;
2325 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2326 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2327 NULL);
2328 return ret;
2331 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2332 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2333 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2335 BOOL ret = FALSE;
2337 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2338 pDecodePara, pvStructInfo, *pcbStructInfo);
2340 __TRY
2342 DWORD bytesNeeded;
2344 if (!cbEncoded)
2345 SetLastError(CRYPT_E_ASN1_EOD);
2346 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2347 SetLastError(CRYPT_E_ASN1_CORRUPT);
2348 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2349 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2350 NULL)))
2352 if (!pvStructInfo)
2353 *pcbStructInfo = bytesNeeded;
2354 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2355 pvStructInfo, pcbStructInfo, bytesNeeded)))
2357 PCRYPT_ATTRIBUTES attrs;
2359 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2360 pvStructInfo = *(BYTE **)pvStructInfo;
2361 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2362 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2363 sizeof(CRYPT_ATTRIBUTES));
2364 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2365 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2366 &bytesNeeded, NULL);
2370 __EXCEPT_PAGE_FAULT
2372 SetLastError(STATUS_ACCESS_VIOLATION);
2374 __ENDTRY
2375 TRACE("returning %d\n", ret);
2376 return ret;
2379 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2380 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2382 CRYPT_ALGORITHM_IDENTIFIER *algo =
2383 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2384 BOOL ret = TRUE;
2385 struct AsnDecodeSequenceItem items[] = {
2386 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2387 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2388 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2389 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2390 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2391 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2394 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2395 pvStructInfo, *pcbStructInfo, pcbDecoded);
2397 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2398 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2399 pcbDecoded, algo ? algo->pszObjId : NULL);
2400 if (ret && pvStructInfo)
2402 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2403 debugstr_a(algo->pszObjId));
2405 return ret;
2408 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2409 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2410 DWORD *pcbDecoded)
2412 BOOL ret = TRUE;
2413 struct AsnDecodeSequenceItem items[] = {
2414 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2415 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2416 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2417 Algorithm.pszObjId) },
2418 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2419 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2420 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2422 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2424 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2425 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2426 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2427 return ret;
2430 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2431 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2432 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2434 BOOL ret = TRUE;
2436 __TRY
2438 DWORD bytesNeeded;
2440 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2441 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2443 if (!pvStructInfo)
2444 *pcbStructInfo = bytesNeeded;
2445 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2446 pvStructInfo, pcbStructInfo, bytesNeeded)))
2448 PCERT_PUBLIC_KEY_INFO info;
2450 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2451 pvStructInfo = *(BYTE **)pvStructInfo;
2452 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2453 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2454 sizeof(CERT_PUBLIC_KEY_INFO);
2455 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2456 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2457 &bytesNeeded, NULL);
2461 __EXCEPT_PAGE_FAULT
2463 SetLastError(STATUS_ACCESS_VIOLATION);
2464 ret = FALSE;
2466 __ENDTRY
2467 return ret;
2470 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2471 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2473 BOOL ret;
2475 if (cbEncoded < 3)
2477 SetLastError(CRYPT_E_ASN1_CORRUPT);
2478 return FALSE;
2480 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2482 SetLastError(CRYPT_E_ASN1_CORRUPT);
2483 return FALSE;
2485 if (pbEncoded[1] > 1)
2487 SetLastError(CRYPT_E_ASN1_CORRUPT);
2488 return FALSE;
2490 if (pcbDecoded)
2491 *pcbDecoded = 3;
2492 if (!pvStructInfo)
2494 *pcbStructInfo = sizeof(BOOL);
2495 ret = TRUE;
2497 else if (*pcbStructInfo < sizeof(BOOL))
2499 *pcbStructInfo = sizeof(BOOL);
2500 SetLastError(ERROR_MORE_DATA);
2501 ret = FALSE;
2503 else
2505 *pcbStructInfo = sizeof(BOOL);
2506 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2507 ret = TRUE;
2509 TRACE("returning %d (%08x)\n", ret, GetLastError());
2510 return ret;
2513 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2514 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2516 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2517 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2518 BOOL ret;
2520 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2521 pvStructInfo, *pcbStructInfo);
2523 if (cbEncoded < 2)
2525 SetLastError(CRYPT_E_ASN1_CORRUPT);
2526 return FALSE;
2528 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2529 if (1 + lenBytes > cbEncoded)
2531 SetLastError(CRYPT_E_ASN1_CORRUPT);
2532 return FALSE;
2534 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2536 switch (pbEncoded[0] & ASN_TYPE_MASK)
2538 case 1: /* rfc822Name */
2539 case 2: /* dNSName */
2540 case 6: /* uniformResourceIdentifier */
2541 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2542 break;
2543 case 4: /* directoryName */
2544 case 7: /* iPAddress */
2545 bytesNeeded += dataLen;
2546 break;
2547 case 8: /* registeredID */
2548 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2549 &dataLen, NULL);
2550 if (ret)
2552 /* FIXME: ugly, shouldn't need to know internals of OID decode
2553 * function to use it.
2555 bytesNeeded += dataLen - sizeof(LPSTR);
2557 break;
2558 case 0: /* otherName */
2559 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2560 SetLastError(CRYPT_E_ASN1_BADTAG);
2561 ret = FALSE;
2562 break;
2563 case 3: /* x400Address, unimplemented */
2564 case 5: /* ediPartyName, unimplemented */
2565 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2566 SetLastError(CRYPT_E_ASN1_BADTAG);
2567 ret = FALSE;
2568 break;
2569 default:
2570 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2571 SetLastError(CRYPT_E_ASN1_CORRUPT);
2572 ret = FALSE;
2574 if (ret)
2576 if (pcbDecoded)
2577 *pcbDecoded = 1 + lenBytes + dataLen;
2578 if (!entry)
2579 *pcbStructInfo = bytesNeeded;
2580 else if (*pcbStructInfo < bytesNeeded)
2582 *pcbStructInfo = bytesNeeded;
2583 SetLastError(ERROR_MORE_DATA);
2584 ret = FALSE;
2586 else
2588 *pcbStructInfo = bytesNeeded;
2589 /* MS used values one greater than the asn1 ones.. sigh */
2590 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
2591 switch (pbEncoded[0] & ASN_TYPE_MASK)
2593 case 1: /* rfc822Name */
2594 case 2: /* dNSName */
2595 case 6: /* uniformResourceIdentifier */
2597 DWORD i;
2599 for (i = 0; i < dataLen; i++)
2600 entry->u.pwszURL[i] =
2601 (WCHAR)pbEncoded[1 + lenBytes + i];
2602 entry->u.pwszURL[i] = 0;
2603 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2604 debugstr_w(entry->u.pwszURL));
2605 break;
2607 case 4: /* directoryName */
2608 /* The data are memory-equivalent with the IPAddress case,
2609 * fall-through
2611 case 7: /* iPAddress */
2612 /* The next data pointer is in the pwszURL spot, that is,
2613 * the first 4 bytes. Need to move it to the next spot.
2615 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2616 entry->u.IPAddress.cbData = dataLen;
2617 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2618 dataLen);
2619 break;
2620 case 8: /* registeredID */
2621 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2622 &entry->u.pszRegisteredID, &dataLen, NULL);
2623 break;
2628 return ret;
2631 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2632 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2633 DWORD *pcbDecoded)
2635 BOOL ret = TRUE;
2636 struct AsnArrayDescriptor arrayDesc = { 0,
2637 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2638 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2639 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2641 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2642 pvStructInfo, *pcbStructInfo, pcbDecoded);
2644 if (info)
2645 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2646 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2647 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2648 info ? info->rgAltEntry : NULL);
2649 return ret;
2652 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2653 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2654 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2655 DWORD *pcbDecoded)
2657 BOOL ret;
2659 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2660 pvStructInfo, *pcbStructInfo, pcbDecoded);
2662 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2663 * place.
2665 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2666 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2667 pcbDecoded);
2668 if (ret && pvStructInfo)
2670 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2672 if (blob->cbData)
2674 DWORD i;
2675 BYTE temp;
2677 for (i = 0; i < blob->cbData / 2; i++)
2679 temp = blob->pbData[i];
2680 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2681 blob->pbData[blob->cbData - i - 1] = temp;
2685 TRACE("returning %d (%08x)\n", ret, GetLastError());
2686 return ret;
2689 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2690 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2691 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2693 BOOL ret;
2695 __TRY
2697 struct AsnDecodeSequenceItem items[] = {
2698 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2699 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2700 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2701 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2702 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2703 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2704 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2705 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2706 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2707 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2708 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2711 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2712 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2713 pcbStructInfo, NULL, NULL);
2715 __EXCEPT_PAGE_FAULT
2717 SetLastError(STATUS_ACCESS_VIOLATION);
2718 ret = FALSE;
2720 __ENDTRY
2721 return ret;
2724 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2725 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2726 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2728 BOOL ret;
2730 __TRY
2732 struct AsnDecodeSequenceItem items[] = {
2733 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2734 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2735 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2736 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2737 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2738 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2739 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2740 AuthorityCertIssuer.rgAltEntry), 0 },
2741 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2742 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2743 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2744 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2745 AuthorityCertSerialNumber.pbData), 0 },
2748 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2749 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2750 pcbStructInfo, NULL, NULL);
2752 __EXCEPT_PAGE_FAULT
2754 SetLastError(STATUS_ACCESS_VIOLATION);
2755 ret = FALSE;
2757 __ENDTRY
2758 return ret;
2761 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
2762 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2763 DWORD *pcbDecoded)
2765 struct AsnDecodeSequenceItem items[] = {
2766 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
2767 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
2768 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
2769 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
2770 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
2771 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
2773 CERT_ACCESS_DESCRIPTION *descr = (CERT_ACCESS_DESCRIPTION *)pvStructInfo;
2775 return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2776 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2777 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
2780 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2781 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2782 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2784 BOOL ret;
2786 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2787 pDecodePara, pvStructInfo, *pcbStructInfo);
2789 __TRY
2791 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2792 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
2793 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
2795 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2796 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2798 __EXCEPT_PAGE_FAULT
2800 SetLastError(STATUS_ACCESS_VIOLATION);
2801 ret = FALSE;
2803 __ENDTRY
2804 return ret;
2807 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
2808 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2810 BOOL ret;
2811 DWORD dataLen;
2813 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2814 pvStructInfo, *pcbStructInfo, pcbDecoded);
2816 /* The caller has already checked the tag, no need to check it again.
2817 * Check the outer length is valid:
2819 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
2821 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2822 DWORD innerLen;
2824 pbEncoded += 1 + lenBytes;
2825 cbEncoded -= 1 + lenBytes;
2826 if (dataLen == CMSG_INDEFINITE_LENGTH)
2827 cbEncoded -= 2; /* space for 0 TLV */
2828 /* Check the inner length is valid: */
2829 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
2831 DWORD decodedLen;
2833 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
2834 pvStructInfo, pcbStructInfo, &decodedLen);
2835 if (dataLen == CMSG_INDEFINITE_LENGTH)
2837 if (*(pbEncoded + decodedLen) != 0 ||
2838 *(pbEncoded + decodedLen + 1) != 0)
2840 TRACE("expected 0 TLV, got {%02x,%02x}\n",
2841 *(pbEncoded + decodedLen),
2842 *(pbEncoded + decodedLen + 1));
2843 SetLastError(CRYPT_E_ASN1_CORRUPT);
2844 ret = FALSE;
2846 else
2847 decodedLen += 2;
2849 if (ret && pcbDecoded)
2851 *pcbDecoded = 1 + lenBytes + decodedLen;
2852 TRACE("decoded %d bytes\n", *pcbDecoded);
2856 return ret;
2859 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
2860 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2861 DWORD *pcbDecoded)
2863 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2864 struct AsnDecodeSequenceItem items[] = {
2865 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2866 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2867 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2868 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2869 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2870 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2871 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2873 BOOL ret;
2875 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2876 pvStructInfo, *pcbStructInfo, pcbDecoded);
2878 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2879 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2880 pcbDecoded, info ? info->pszObjId : NULL);
2881 return ret;
2884 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2885 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2886 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2888 BOOL ret = FALSE;
2890 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2891 pDecodePara, pvStructInfo, *pcbStructInfo);
2893 __TRY
2895 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
2896 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2897 if (ret && pvStructInfo)
2899 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2900 pcbStructInfo, *pcbStructInfo);
2901 if (ret)
2903 CRYPT_CONTENT_INFO *info;
2905 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2906 pvStructInfo = *(BYTE **)pvStructInfo;
2907 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2908 info->pszObjId = (LPSTR)((BYTE *)info +
2909 sizeof(CRYPT_CONTENT_INFO));
2910 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
2911 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2912 pcbStructInfo, NULL);
2916 __EXCEPT_PAGE_FAULT
2918 SetLastError(STATUS_ACCESS_VIOLATION);
2920 __ENDTRY
2921 return ret;
2924 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2925 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2926 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2928 BOOL ret;
2929 struct AsnDecodeSequenceItem items[] = {
2930 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2931 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2932 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2933 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2934 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2935 0 },
2936 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2937 CRYPT_AsnDecodePKCSContentInfoInternal,
2938 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2939 ContentInfo.pszObjId), 0 },
2940 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2941 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2942 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2945 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2946 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
2947 NULL, NULL);
2948 return ret;
2951 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2952 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2953 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2955 BOOL ret = TRUE;
2957 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2958 pDecodePara, pvStructInfo, *pcbStructInfo);
2960 __TRY
2962 DWORD bytesNeeded;
2964 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2965 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2967 if (!pvStructInfo)
2968 *pcbStructInfo = bytesNeeded;
2969 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2970 pvStructInfo, pcbStructInfo, bytesNeeded)))
2972 CERT_ALT_NAME_INFO *name;
2974 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2975 pvStructInfo = *(BYTE **)pvStructInfo;
2976 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2977 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2978 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2979 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2980 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2981 &bytesNeeded, NULL);
2985 __EXCEPT_PAGE_FAULT
2987 SetLastError(STATUS_ACCESS_VIOLATION);
2988 ret = FALSE;
2990 __ENDTRY
2991 return ret;
2994 struct PATH_LEN_CONSTRAINT
2996 BOOL fPathLenConstraint;
2997 DWORD dwPathLenConstraint;
3000 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3001 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3002 DWORD *pcbDecoded)
3004 BOOL ret = TRUE;
3005 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3007 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3008 pvStructInfo, *pcbStructInfo, pcbDecoded);
3010 if (!pvStructInfo)
3012 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3013 &size, pcbDecoded);
3014 *pcbStructInfo = bytesNeeded;
3016 else if (*pcbStructInfo < bytesNeeded)
3018 SetLastError(ERROR_MORE_DATA);
3019 *pcbStructInfo = bytesNeeded;
3020 ret = FALSE;
3022 else
3024 struct PATH_LEN_CONSTRAINT *constraint =
3025 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
3027 *pcbStructInfo = bytesNeeded;
3028 size = sizeof(constraint->dwPathLenConstraint);
3029 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3030 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3031 if (ret)
3032 constraint->fPathLenConstraint = TRUE;
3033 TRACE("got an int, dwPathLenConstraint is %d\n",
3034 constraint->dwPathLenConstraint);
3036 TRACE("returning %d (%08x)\n", ret, GetLastError());
3037 return ret;
3040 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3041 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3042 DWORD *pcbDecoded)
3044 BOOL ret;
3045 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3046 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3047 offsetof(CERT_NAME_BLOB, pbData) };
3048 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
3050 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3051 pvStructInfo, *pcbStructInfo, pcbDecoded);
3053 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3054 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3055 entries ? entries->rgItems : NULL);
3056 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3057 return ret;
3060 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3061 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3062 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3064 BOOL ret;
3066 __TRY
3068 struct AsnDecodeSequenceItem items[] = {
3069 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3070 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3071 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3072 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3073 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3074 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3075 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3076 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3077 sizeof(struct GenericArray), TRUE, TRUE,
3078 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3081 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3082 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3083 pcbStructInfo, NULL, NULL);
3085 __EXCEPT_PAGE_FAULT
3087 SetLastError(STATUS_ACCESS_VIOLATION);
3088 ret = FALSE;
3090 __ENDTRY
3091 return ret;
3094 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3095 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3096 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3098 BOOL ret;
3100 __TRY
3102 struct AsnDecodeSequenceItem items[] = {
3103 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3104 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3105 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3106 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3107 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3110 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3111 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3112 pcbStructInfo, NULL, NULL);
3114 __EXCEPT_PAGE_FAULT
3116 SetLastError(STATUS_ACCESS_VIOLATION);
3117 ret = FALSE;
3119 __ENDTRY
3120 return ret;
3123 #define RSA1_MAGIC 0x31415352
3125 struct DECODED_RSA_PUB_KEY
3127 DWORD pubexp;
3128 CRYPT_INTEGER_BLOB modulus;
3131 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3132 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3133 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3135 BOOL ret;
3137 __TRY
3139 struct AsnDecodeSequenceItem items[] = {
3140 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3141 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3142 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3143 0 },
3144 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3145 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3147 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3148 DWORD size = 0;
3150 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3151 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3152 &size, NULL, NULL);
3153 if (ret)
3155 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3156 decodedKey->modulus.cbData;
3158 if (!pvStructInfo)
3160 *pcbStructInfo = bytesNeeded;
3161 ret = TRUE;
3163 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3164 pvStructInfo, pcbStructInfo, bytesNeeded)))
3166 BLOBHEADER *hdr;
3167 RSAPUBKEY *rsaPubKey;
3169 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3170 pvStructInfo = *(BYTE **)pvStructInfo;
3171 hdr = (BLOBHEADER *)pvStructInfo;
3172 hdr->bType = PUBLICKEYBLOB;
3173 hdr->bVersion = CUR_BLOB_VERSION;
3174 hdr->reserved = 0;
3175 hdr->aiKeyAlg = CALG_RSA_KEYX;
3176 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3177 sizeof(BLOBHEADER));
3178 rsaPubKey->magic = RSA1_MAGIC;
3179 rsaPubKey->pubexp = decodedKey->pubexp;
3180 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3181 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3182 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3183 decodedKey->modulus.cbData);
3185 LocalFree(decodedKey);
3188 __EXCEPT_PAGE_FAULT
3190 SetLastError(STATUS_ACCESS_VIOLATION);
3191 ret = FALSE;
3193 __ENDTRY
3194 return ret;
3197 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
3198 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3199 DWORD *pcbDecoded)
3201 BOOL ret;
3202 DWORD bytesNeeded, dataLen;
3204 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3205 pvStructInfo, *pcbStructInfo, pcbDecoded);
3207 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3209 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3211 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3212 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
3213 else
3214 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
3215 if (pcbDecoded)
3216 *pcbDecoded = 1 + lenBytes + dataLen;
3217 if (!pvStructInfo)
3218 *pcbStructInfo = bytesNeeded;
3219 else if (*pcbStructInfo < bytesNeeded)
3221 SetLastError(ERROR_MORE_DATA);
3222 *pcbStructInfo = bytesNeeded;
3223 ret = FALSE;
3225 else
3227 CRYPT_DATA_BLOB *blob;
3229 *pcbStructInfo = bytesNeeded;
3230 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3231 blob->cbData = dataLen;
3232 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3233 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
3234 else
3236 assert(blob->pbData);
3237 if (blob->cbData)
3238 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
3239 blob->cbData);
3243 return ret;
3246 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
3247 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3248 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3250 BOOL ret;
3252 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3253 pDecodePara, pvStructInfo, *pcbStructInfo);
3255 __TRY
3257 DWORD bytesNeeded;
3259 if (!cbEncoded)
3261 SetLastError(CRYPT_E_ASN1_CORRUPT);
3262 ret = FALSE;
3264 else if (pbEncoded[0] != ASN_OCTETSTRING)
3266 SetLastError(CRYPT_E_ASN1_BADTAG);
3267 ret = FALSE;
3269 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3270 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3272 if (!pvStructInfo)
3273 *pcbStructInfo = bytesNeeded;
3274 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3275 pvStructInfo, pcbStructInfo, bytesNeeded)))
3277 CRYPT_DATA_BLOB *blob;
3279 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3280 pvStructInfo = *(BYTE **)pvStructInfo;
3281 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3282 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
3283 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3284 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3285 &bytesNeeded, NULL);
3289 __EXCEPT_PAGE_FAULT
3291 SetLastError(STATUS_ACCESS_VIOLATION);
3292 ret = FALSE;
3294 __ENDTRY
3295 return ret;
3298 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3299 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3301 BOOL ret;
3302 DWORD bytesNeeded, dataLen;
3303 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3305 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3306 pvStructInfo, *pcbStructInfo, pcbDecoded);
3308 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3310 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3311 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3312 else
3313 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3314 if (pcbDecoded)
3315 *pcbDecoded = 1 + lenBytes + dataLen;
3316 if (!pvStructInfo)
3317 *pcbStructInfo = bytesNeeded;
3318 else if (*pcbStructInfo < bytesNeeded)
3320 *pcbStructInfo = bytesNeeded;
3321 SetLastError(ERROR_MORE_DATA);
3322 ret = FALSE;
3324 else
3326 CRYPT_BIT_BLOB *blob;
3328 *pcbStructInfo = bytesNeeded;
3329 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3330 blob->cbData = dataLen - 1;
3331 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3332 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3334 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3336 else
3338 assert(blob->pbData);
3339 if (blob->cbData)
3341 BYTE mask = 0xff << blob->cUnusedBits;
3343 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3344 blob->cbData);
3345 blob->pbData[blob->cbData - 1] &= mask;
3350 return ret;
3353 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3354 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3355 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3357 BOOL ret;
3359 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3360 pDecodePara, pvStructInfo, pcbStructInfo);
3362 __TRY
3364 DWORD bytesNeeded;
3366 if (!cbEncoded)
3368 SetLastError(CRYPT_E_ASN1_CORRUPT);
3369 ret = FALSE;
3371 else if (pbEncoded[0] != ASN_BITSTRING)
3373 SetLastError(CRYPT_E_ASN1_BADTAG);
3374 ret = FALSE;
3376 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3377 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3379 if (!pvStructInfo)
3380 *pcbStructInfo = bytesNeeded;
3381 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3382 pvStructInfo, pcbStructInfo, bytesNeeded)))
3384 CRYPT_BIT_BLOB *blob;
3386 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3387 pvStructInfo = *(BYTE **)pvStructInfo;
3388 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3389 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3390 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3391 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3392 &bytesNeeded, NULL);
3396 __EXCEPT_PAGE_FAULT
3398 SetLastError(STATUS_ACCESS_VIOLATION);
3399 ret = FALSE;
3401 __ENDTRY
3402 TRACE("returning %d (%08x)\n", ret, GetLastError());
3403 return ret;
3406 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
3407 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3408 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3410 BOOL ret;
3411 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3412 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3413 DWORD size = sizeof(buf);
3415 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3416 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, buf,
3417 &size, pcbDecoded);
3418 if (ret)
3420 if (!pvStructInfo)
3421 *pcbStructInfo = sizeof(int);
3422 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3424 int val, i;
3426 if (blob->pbData[blob->cbData - 1] & 0x80)
3428 /* initialize to a negative value to sign-extend */
3429 val = -1;
3431 else
3432 val = 0;
3433 for (i = 0; i < blob->cbData; i++)
3435 val <<= 8;
3436 val |= blob->pbData[blob->cbData - i - 1];
3438 memcpy(pvStructInfo, &val, sizeof(int));
3441 else if (GetLastError() == ERROR_MORE_DATA)
3442 SetLastError(CRYPT_E_ASN1_LARGE);
3443 return ret;
3446 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3447 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3448 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3450 BOOL ret;
3452 __TRY
3454 DWORD bytesNeeded;
3456 if (!cbEncoded)
3458 SetLastError(CRYPT_E_ASN1_EOD);
3459 ret = FALSE;
3461 else if (pbEncoded[0] != ASN_INTEGER)
3463 SetLastError(CRYPT_E_ASN1_BADTAG);
3464 ret = FALSE;
3466 else
3467 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3468 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3469 if (ret)
3471 if (!pvStructInfo)
3472 *pcbStructInfo = bytesNeeded;
3473 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3474 pvStructInfo, pcbStructInfo, bytesNeeded)))
3476 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3477 pvStructInfo = *(BYTE **)pvStructInfo;
3478 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3479 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3480 &bytesNeeded, NULL);
3484 __EXCEPT_PAGE_FAULT
3486 SetLastError(STATUS_ACCESS_VIOLATION);
3487 ret = FALSE;
3489 __ENDTRY
3490 return ret;
3493 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3494 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3495 DWORD *pcbDecoded)
3497 BOOL ret;
3498 DWORD bytesNeeded, dataLen;
3500 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3502 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3504 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3505 if (pcbDecoded)
3506 *pcbDecoded = 1 + lenBytes + dataLen;
3507 if (!pvStructInfo)
3508 *pcbStructInfo = bytesNeeded;
3509 else if (*pcbStructInfo < bytesNeeded)
3511 *pcbStructInfo = bytesNeeded;
3512 SetLastError(ERROR_MORE_DATA);
3513 ret = FALSE;
3515 else
3517 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3519 *pcbStructInfo = bytesNeeded;
3520 blob->cbData = dataLen;
3521 assert(blob->pbData);
3522 if (blob->cbData)
3524 DWORD i;
3526 for (i = 0; i < blob->cbData; i++)
3528 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3529 dataLen - i - 1);
3534 return ret;
3537 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3538 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3539 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3541 BOOL ret;
3543 __TRY
3545 DWORD bytesNeeded;
3547 if (pbEncoded[0] != ASN_INTEGER)
3549 SetLastError(CRYPT_E_ASN1_BADTAG);
3550 ret = FALSE;
3552 else
3553 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3554 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3555 if (ret)
3557 if (!pvStructInfo)
3558 *pcbStructInfo = bytesNeeded;
3559 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3560 pvStructInfo, pcbStructInfo, bytesNeeded)))
3562 CRYPT_INTEGER_BLOB *blob;
3564 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3565 pvStructInfo = *(BYTE **)pvStructInfo;
3566 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3567 blob->pbData = (BYTE *)pvStructInfo +
3568 sizeof(CRYPT_INTEGER_BLOB);
3569 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3570 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3571 &bytesNeeded, NULL);
3575 __EXCEPT_PAGE_FAULT
3577 SetLastError(STATUS_ACCESS_VIOLATION);
3578 ret = FALSE;
3580 __ENDTRY
3581 return ret;
3584 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3585 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3586 DWORD *pcbDecoded)
3588 BOOL ret;
3590 if (pbEncoded[0] == ASN_INTEGER)
3592 DWORD bytesNeeded, dataLen;
3594 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3596 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3598 if (pcbDecoded)
3599 *pcbDecoded = 1 + lenBytes + dataLen;
3600 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3601 if (!pvStructInfo)
3602 *pcbStructInfo = bytesNeeded;
3603 else if (*pcbStructInfo < bytesNeeded)
3605 *pcbStructInfo = bytesNeeded;
3606 SetLastError(ERROR_MORE_DATA);
3607 ret = FALSE;
3609 else
3611 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3613 *pcbStructInfo = bytesNeeded;
3614 blob->cbData = dataLen;
3615 assert(blob->pbData);
3616 /* remove leading zero byte if it exists */
3617 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3619 blob->cbData--;
3620 blob->pbData++;
3622 if (blob->cbData)
3624 DWORD i;
3626 for (i = 0; i < blob->cbData; i++)
3628 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3629 dataLen - i - 1);
3635 else
3637 SetLastError(CRYPT_E_ASN1_BADTAG);
3638 ret = FALSE;
3640 return ret;
3643 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3644 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3645 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3647 BOOL ret;
3649 __TRY
3651 DWORD bytesNeeded;
3653 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
3654 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3656 if (!pvStructInfo)
3657 *pcbStructInfo = bytesNeeded;
3658 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3659 pvStructInfo, pcbStructInfo, bytesNeeded)))
3661 CRYPT_INTEGER_BLOB *blob;
3663 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3664 pvStructInfo = *(BYTE **)pvStructInfo;
3665 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3666 blob->pbData = (BYTE *)pvStructInfo +
3667 sizeof(CRYPT_INTEGER_BLOB);
3668 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
3669 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3670 &bytesNeeded, NULL);
3674 __EXCEPT_PAGE_FAULT
3676 SetLastError(STATUS_ACCESS_VIOLATION);
3677 ret = FALSE;
3679 __ENDTRY
3680 return ret;
3683 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3684 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3685 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3687 BOOL ret;
3689 if (!pvStructInfo)
3691 *pcbStructInfo = sizeof(int);
3692 return TRUE;
3694 __TRY
3696 if (pbEncoded[0] == ASN_ENUMERATED)
3698 unsigned int val = 0, i;
3700 if (cbEncoded <= 1)
3702 SetLastError(CRYPT_E_ASN1_EOD);
3703 ret = FALSE;
3705 else if (pbEncoded[1] == 0)
3707 SetLastError(CRYPT_E_ASN1_CORRUPT);
3708 ret = FALSE;
3710 else
3712 /* A little strange looking, but we have to accept a sign byte:
3713 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3714 * assuming a small length is okay here, it has to be in short
3715 * form.
3717 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3719 SetLastError(CRYPT_E_ASN1_LARGE);
3720 return FALSE;
3722 for (i = 0; i < pbEncoded[1]; i++)
3724 val <<= 8;
3725 val |= pbEncoded[2 + i];
3727 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3728 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3730 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3731 pvStructInfo = *(BYTE **)pvStructInfo;
3732 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3736 else
3738 SetLastError(CRYPT_E_ASN1_BADTAG);
3739 ret = FALSE;
3742 __EXCEPT_PAGE_FAULT
3744 SetLastError(STATUS_ACCESS_VIOLATION);
3745 ret = FALSE;
3747 __ENDTRY
3748 return ret;
3751 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3752 * if it fails.
3754 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3755 do { \
3756 BYTE i; \
3758 (word) = 0; \
3759 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3761 if (!isdigit(*(pbEncoded))) \
3763 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3764 ret = FALSE; \
3766 else \
3768 (word) *= 10; \
3769 (word) += *(pbEncoded)++ - '0'; \
3772 } while (0)
3774 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3775 SYSTEMTIME *sysTime)
3777 BOOL ret = TRUE;
3779 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3781 WORD hours, minutes = 0;
3782 BYTE sign = *pbEncoded++;
3784 len--;
3785 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3786 if (ret && hours >= 24)
3788 SetLastError(CRYPT_E_ASN1_CORRUPT);
3789 ret = FALSE;
3791 else if (len >= 2)
3793 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3794 if (ret && minutes >= 60)
3796 SetLastError(CRYPT_E_ASN1_CORRUPT);
3797 ret = FALSE;
3800 if (ret)
3802 if (sign == '+')
3804 sysTime->wHour += hours;
3805 sysTime->wMinute += minutes;
3807 else
3809 if (hours > sysTime->wHour)
3811 sysTime->wDay--;
3812 sysTime->wHour = 24 - (hours - sysTime->wHour);
3814 else
3815 sysTime->wHour -= hours;
3816 if (minutes > sysTime->wMinute)
3818 sysTime->wHour--;
3819 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3821 else
3822 sysTime->wMinute -= minutes;
3826 return ret;
3829 #define MIN_ENCODED_TIME_LENGTH 10
3831 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3832 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3833 DWORD *pcbDecoded)
3835 BOOL ret = FALSE;
3837 if (pbEncoded[0] == ASN_UTCTIME)
3839 if (cbEncoded <= 1)
3840 SetLastError(CRYPT_E_ASN1_EOD);
3841 else if (pbEncoded[1] > 0x7f)
3843 /* long-form date strings really can't be valid */
3844 SetLastError(CRYPT_E_ASN1_CORRUPT);
3846 else
3848 SYSTEMTIME sysTime = { 0 };
3849 BYTE len = pbEncoded[1];
3851 if (len < MIN_ENCODED_TIME_LENGTH)
3852 SetLastError(CRYPT_E_ASN1_CORRUPT);
3853 else
3855 ret = TRUE;
3856 if (pcbDecoded)
3857 *pcbDecoded = 2 + len;
3858 pbEncoded += 2;
3859 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3860 if (sysTime.wYear >= 50)
3861 sysTime.wYear += 1900;
3862 else
3863 sysTime.wYear += 2000;
3864 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3865 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3866 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3867 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3868 if (ret && len > 0)
3870 if (len >= 2 && isdigit(*pbEncoded) &&
3871 isdigit(*(pbEncoded + 1)))
3872 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3873 sysTime.wSecond);
3874 else if (isdigit(*pbEncoded))
3875 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3876 sysTime.wSecond);
3877 if (ret)
3878 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3879 &sysTime);
3881 if (ret)
3883 if (!pvStructInfo)
3884 *pcbStructInfo = sizeof(FILETIME);
3885 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3886 sizeof(FILETIME))))
3887 ret = SystemTimeToFileTime(&sysTime,
3888 (FILETIME *)pvStructInfo);
3893 else
3894 SetLastError(CRYPT_E_ASN1_BADTAG);
3895 return ret;
3898 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3899 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3900 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3902 BOOL ret = FALSE;
3904 __TRY
3906 DWORD bytesNeeded;
3908 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3909 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3910 if (ret)
3912 if (!pvStructInfo)
3913 *pcbStructInfo = bytesNeeded;
3914 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3915 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3917 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3918 pvStructInfo = *(BYTE **)pvStructInfo;
3919 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3920 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3921 &bytesNeeded, NULL);
3925 __EXCEPT_PAGE_FAULT
3927 SetLastError(STATUS_ACCESS_VIOLATION);
3929 __ENDTRY
3930 return ret;
3933 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3934 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3935 DWORD *pcbDecoded)
3937 BOOL ret = FALSE;
3939 if (pbEncoded[0] == ASN_GENERALTIME)
3941 if (cbEncoded <= 1)
3942 SetLastError(CRYPT_E_ASN1_EOD);
3943 else if (pbEncoded[1] > 0x7f)
3945 /* long-form date strings really can't be valid */
3946 SetLastError(CRYPT_E_ASN1_CORRUPT);
3948 else
3950 BYTE len = pbEncoded[1];
3952 if (len < MIN_ENCODED_TIME_LENGTH)
3953 SetLastError(CRYPT_E_ASN1_CORRUPT);
3954 else
3956 SYSTEMTIME sysTime = { 0 };
3958 ret = TRUE;
3959 if (pcbDecoded)
3960 *pcbDecoded = 2 + len;
3961 pbEncoded += 2;
3962 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3963 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3964 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3965 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3966 if (ret && len > 0)
3968 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3969 sysTime.wMinute);
3970 if (ret && len > 0)
3971 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3972 sysTime.wSecond);
3973 if (ret && len > 0 && (*pbEncoded == '.' ||
3974 *pbEncoded == ','))
3976 BYTE digits;
3978 pbEncoded++;
3979 len--;
3980 /* workaround macro weirdness */
3981 digits = min(len, 3);
3982 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3983 sysTime.wMilliseconds);
3985 if (ret)
3986 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3987 &sysTime);
3989 if (ret)
3991 if (!pvStructInfo)
3992 *pcbStructInfo = sizeof(FILETIME);
3993 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3994 sizeof(FILETIME))))
3995 ret = SystemTimeToFileTime(&sysTime,
3996 (FILETIME *)pvStructInfo);
4001 else
4002 SetLastError(CRYPT_E_ASN1_BADTAG);
4003 return ret;
4006 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4007 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4008 DWORD *pcbDecoded)
4010 BOOL ret;
4011 InternalDecodeFunc decode = NULL;
4013 if (pbEncoded[0] == ASN_UTCTIME)
4014 decode = CRYPT_AsnDecodeUtcTimeInternal;
4015 else if (pbEncoded[0] == ASN_GENERALTIME)
4016 decode = CRYPT_AsnDecodeGeneralizedTime;
4017 if (decode)
4018 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
4019 pcbStructInfo, pcbDecoded);
4020 else
4022 SetLastError(CRYPT_E_ASN1_BADTAG);
4023 ret = FALSE;
4025 return ret;
4028 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
4029 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4030 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4032 BOOL ret;
4034 __TRY
4036 DWORD bytesNeeded;
4038 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4039 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4040 if (ret)
4042 if (!pvStructInfo)
4043 *pcbStructInfo = bytesNeeded;
4044 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4045 pvStructInfo, pcbStructInfo, bytesNeeded)))
4047 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4048 pvStructInfo = *(BYTE **)pvStructInfo;
4049 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4050 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4051 &bytesNeeded, NULL);
4055 __EXCEPT_PAGE_FAULT
4057 SetLastError(STATUS_ACCESS_VIOLATION);
4058 ret = FALSE;
4060 __ENDTRY
4061 return ret;
4064 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
4065 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4066 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4068 BOOL ret = TRUE;
4070 __TRY
4072 if (pbEncoded[0] == ASN_SEQUENCEOF)
4074 DWORD bytesNeeded, dataLen, remainingLen, cValue;
4076 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4078 BYTE lenBytes;
4079 const BYTE *ptr;
4081 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4082 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
4083 cValue = 0;
4084 ptr = pbEncoded + 1 + lenBytes;
4085 remainingLen = dataLen;
4086 while (ret && remainingLen)
4088 DWORD nextLen;
4090 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4091 if (ret)
4093 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4095 remainingLen -= 1 + nextLenBytes + nextLen;
4096 ptr += 1 + nextLenBytes + nextLen;
4097 bytesNeeded += sizeof(CRYPT_DER_BLOB);
4098 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
4099 bytesNeeded += 1 + nextLenBytes + nextLen;
4100 cValue++;
4103 if (ret)
4105 CRYPT_SEQUENCE_OF_ANY *seq;
4106 BYTE *nextPtr;
4107 DWORD i;
4109 if (!pvStructInfo)
4110 *pcbStructInfo = bytesNeeded;
4111 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4112 pvStructInfo, pcbStructInfo, bytesNeeded)))
4114 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4115 pvStructInfo = *(BYTE **)pvStructInfo;
4116 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
4117 seq->cValue = cValue;
4118 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
4119 sizeof(*seq));
4120 nextPtr = (BYTE *)seq->rgValue +
4121 cValue * sizeof(CRYPT_DER_BLOB);
4122 ptr = pbEncoded + 1 + lenBytes;
4123 remainingLen = dataLen;
4124 i = 0;
4125 while (ret && remainingLen)
4127 DWORD nextLen;
4129 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4130 if (ret)
4132 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4134 seq->rgValue[i].cbData = 1 + nextLenBytes +
4135 nextLen;
4136 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4137 seq->rgValue[i].pbData = (BYTE *)ptr;
4138 else
4140 seq->rgValue[i].pbData = nextPtr;
4141 memcpy(nextPtr, ptr, 1 + nextLenBytes +
4142 nextLen);
4143 nextPtr += 1 + nextLenBytes + nextLen;
4145 remainingLen -= 1 + nextLenBytes + nextLen;
4146 ptr += 1 + nextLenBytes + nextLen;
4147 i++;
4154 else
4156 SetLastError(CRYPT_E_ASN1_BADTAG);
4157 ret = FALSE;
4160 __EXCEPT_PAGE_FAULT
4162 SetLastError(STATUS_ACCESS_VIOLATION);
4163 ret = FALSE;
4165 __ENDTRY
4166 return ret;
4169 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4170 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4171 DWORD *pcbDecoded)
4173 BOOL ret;
4175 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
4177 DWORD bytesNeeded, dataLen;
4179 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4181 struct AsnArrayDescriptor arrayDesc = {
4182 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
4183 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
4184 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
4185 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4186 DWORD nameLen;
4188 if (dataLen)
4190 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4191 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4192 0, NULL, NULL, &nameLen, NULL, NULL);
4193 /* The CERT_ALT_NAME_INFO's size is included by CRYPT_AsnDecodeArray
4194 * as the sizeof(struct GenericArray), so don't include it in the
4195 * total bytes needed.
4197 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
4198 sizeof(CERT_ALT_NAME_INFO);
4200 else
4201 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
4202 if (pcbDecoded)
4203 *pcbDecoded = 1 + lenBytes + dataLen;
4204 if (!pvStructInfo)
4205 *pcbStructInfo = bytesNeeded;
4206 else if (*pcbStructInfo < bytesNeeded)
4208 *pcbStructInfo = bytesNeeded;
4209 SetLastError(ERROR_MORE_DATA);
4210 ret = FALSE;
4212 else
4214 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
4216 *pcbStructInfo = bytesNeeded;
4217 if (dataLen)
4219 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
4220 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4221 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4222 0, NULL, &name->u.FullName, &nameLen, NULL,
4223 name->u.FullName.rgAltEntry);
4225 else
4226 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
4230 else
4232 SetLastError(CRYPT_E_ASN1_BADTAG);
4233 ret = FALSE;
4235 return ret;
4238 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
4239 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4241 struct AsnDecodeSequenceItem items[] = {
4242 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
4243 DistPointName), CRYPT_AsnDecodeDistPointName,
4244 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
4245 DistPointName.u.FullName.rgAltEntry), 0 },
4246 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
4247 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
4248 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
4249 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
4250 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
4251 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
4253 BOOL ret;
4255 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4256 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4257 pcbDecoded, NULL);
4258 return ret;
4261 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
4262 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4263 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4265 BOOL ret;
4267 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4268 pDecodePara, pvStructInfo, *pcbStructInfo);
4270 __TRY
4272 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4273 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
4274 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
4276 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4277 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4279 __EXCEPT_PAGE_FAULT
4281 SetLastError(STATUS_ACCESS_VIOLATION);
4282 ret = FALSE;
4284 __ENDTRY
4285 return ret;
4288 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
4289 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4290 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4292 BOOL ret;
4294 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4295 pDecodePara, pvStructInfo, *pcbStructInfo);
4297 __TRY
4299 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4300 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4302 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4303 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4305 __EXCEPT_PAGE_FAULT
4307 SetLastError(STATUS_ACCESS_VIOLATION);
4308 ret = FALSE;
4310 __ENDTRY
4311 return ret;
4314 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4315 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4316 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4318 BOOL ret;
4320 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4321 pDecodePara, pvStructInfo, *pcbStructInfo);
4323 __TRY
4325 struct AsnDecodeSequenceItem items[] = {
4326 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4327 DistPointName), CRYPT_AsnDecodeDistPointName,
4328 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4329 offsetof(CRL_ISSUING_DIST_POINT,
4330 DistPointName.u.FullName.rgAltEntry), 0 },
4331 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4332 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4333 FALSE, 0 },
4334 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4335 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4336 FALSE, 0 },
4337 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4338 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4339 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4340 OnlySomeReasonFlags.pbData), 0 },
4341 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4342 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4345 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4346 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4347 pcbStructInfo, NULL, NULL);
4349 __EXCEPT_PAGE_FAULT
4351 SetLastError(STATUS_ACCESS_VIOLATION);
4352 ret = FALSE;
4354 __ENDTRY
4355 return ret;
4358 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
4359 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4360 DWORD *pcbDecoded)
4362 BOOL ret = FALSE;
4364 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4365 pvStructInfo, *pcbStructInfo, pcbDecoded);
4367 if (!cbEncoded)
4369 SetLastError(CRYPT_E_ASN1_EOD);
4370 return FALSE;
4372 if (pbEncoded[0] != (ASN_CONTEXT | 1))
4374 SetLastError(CRYPT_E_ASN1_BADTAG);
4375 return FALSE;
4377 /* The BOOL is implicit: if the integer is present, then it's TRUE */
4378 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
4379 pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo,
4380 pcbDecoded);
4381 if (ret && pvStructInfo)
4382 *(BOOL *)pvStructInfo = TRUE;
4383 TRACE("returning %d\n", ret);
4384 return ret;
4387 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
4388 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4389 DWORD *pcbDecoded)
4391 BOOL ret;
4392 struct AsnDecodeSequenceItem items[] = {
4393 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
4394 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
4395 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
4396 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
4397 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
4398 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
4399 CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0,
4400 0 },
4402 CERT_GENERAL_SUBTREE *subtree = (CERT_GENERAL_SUBTREE *)pvStructInfo;
4404 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4405 pvStructInfo, *pcbStructInfo, pcbDecoded);
4407 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4408 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4409 pcbDecoded, subtree ? (BYTE *)subtree->Base.u.pwszURL : NULL);
4410 if (pcbDecoded)
4412 TRACE("%d\n", *pcbDecoded);
4413 if (*pcbDecoded < cbEncoded)
4414 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
4415 *(pbEncoded + *pcbDecoded + 1));
4417 TRACE("returning %d\n", ret);
4418 return ret;
4421 static BOOL CRYPT_AsnDecodeSubtreeArray(const BYTE *pbEncoded,
4422 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4423 DWORD *pcbDecoded)
4425 BOOL ret = TRUE;
4426 struct AsnArrayDescriptor arrayDesc = { 0,
4427 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4428 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4429 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4431 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4432 pvStructInfo, *pcbStructInfo, pcbDecoded);
4434 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4435 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4436 array ? array->rgItems : NULL);
4437 return ret;
4441 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
4442 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4443 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4445 BOOL ret = FALSE;
4447 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4448 pDecodePara, pvStructInfo, *pcbStructInfo);
4450 __TRY
4452 struct AsnDecodeSequenceItem items[] = {
4453 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4454 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
4455 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4456 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
4457 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
4458 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4459 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4460 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
4463 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4464 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4465 pcbStructInfo, NULL, NULL);
4467 __EXCEPT_PAGE_FAULT
4469 SetLastError(STATUS_ACCESS_VIOLATION);
4471 __ENDTRY
4472 return ret;
4475 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
4476 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4477 DWORD *pcbDecoded)
4479 BOOL ret;
4480 struct AsnDecodeSequenceItem items[] = {
4481 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4482 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4483 Issuer.pbData) },
4484 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4485 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4486 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4488 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4489 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4491 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4492 pvStructInfo, *pcbStructInfo, pcbDecoded);
4494 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4495 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4496 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4497 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4499 SetLastError(CRYPT_E_ASN1_CORRUPT);
4500 ret = FALSE;
4502 TRACE("returning %d\n", ret);
4503 return ret;
4506 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4507 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4508 DWORD *pcbDecoded)
4510 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4511 struct AsnDecodeSequenceItem items[] = {
4512 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4513 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4514 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4515 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4516 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4517 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4518 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4519 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4520 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4521 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4522 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4523 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4524 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4525 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4526 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4527 HashEncryptionAlgorithm.pszObjId), 0 },
4528 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4529 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4530 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4531 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4532 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4533 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4534 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4536 BOOL ret;
4538 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4539 pvStructInfo, *pcbStructInfo);
4541 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4542 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4543 pcbDecoded, info ? info->Issuer.pbData : NULL);
4544 return ret;
4547 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4548 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4549 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4551 BOOL ret = FALSE;
4553 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4554 pDecodePara, pvStructInfo, *pcbStructInfo);
4556 __TRY
4558 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4559 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4560 if (ret && pvStructInfo)
4562 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4563 pcbStructInfo, *pcbStructInfo);
4564 if (ret)
4566 CMSG_SIGNER_INFO *info;
4568 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4569 pvStructInfo = *(BYTE **)pvStructInfo;
4570 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4571 info->Issuer.pbData = ((BYTE *)info +
4572 sizeof(CMSG_SIGNER_INFO));
4573 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4574 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4575 pcbStructInfo, NULL);
4579 __EXCEPT_PAGE_FAULT
4581 SetLastError(STATUS_ACCESS_VIOLATION);
4583 __ENDTRY
4584 TRACE("returning %d\n", ret);
4585 return ret;
4588 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
4589 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4590 DWORD *pcbDecoded)
4592 CERT_ID *id = (CERT_ID *)pvStructInfo;
4593 BOOL ret = FALSE;
4595 if (*pbEncoded == ASN_SEQUENCEOF)
4597 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
4598 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
4599 if (ret)
4601 if (id)
4602 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
4603 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
4604 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4605 sizeof(CERT_ISSUER_SERIAL_NUMBER);
4606 else
4607 *pcbStructInfo = sizeof(CERT_ID);
4610 else if (*pbEncoded == (ASN_CONTEXT | 0))
4612 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
4613 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
4614 if (ret)
4616 if (id)
4617 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
4618 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
4619 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4620 sizeof(CRYPT_DATA_BLOB);
4621 else
4622 *pcbStructInfo = sizeof(CERT_ID);
4625 else
4626 SetLastError(CRYPT_E_ASN1_BADTAG);
4627 return ret;
4630 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
4631 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4632 DWORD *pcbDecoded)
4634 CMSG_CMS_SIGNER_INFO *info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4635 struct AsnDecodeSequenceItem items[] = {
4636 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
4637 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4638 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
4639 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
4640 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
4641 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
4642 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4643 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4644 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4645 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
4646 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4647 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4648 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
4649 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4650 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
4651 HashEncryptionAlgorithm.pszObjId), 0 },
4652 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
4653 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4654 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
4655 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4656 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
4657 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4658 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4660 BOOL ret;
4662 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4663 pvStructInfo, *pcbStructInfo);
4665 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4666 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4667 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
4668 return ret;
4671 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
4672 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4673 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4675 BOOL ret = FALSE;
4677 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4678 pDecodePara, pvStructInfo, *pcbStructInfo);
4680 __TRY
4682 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
4683 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4684 if (ret && pvStructInfo)
4686 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4687 pcbStructInfo, *pcbStructInfo);
4688 if (ret)
4690 CMSG_CMS_SIGNER_INFO *info;
4692 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4693 pvStructInfo = *(BYTE **)pvStructInfo;
4694 info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4695 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
4696 sizeof(CMSG_CMS_SIGNER_INFO));
4697 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
4698 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4699 pcbStructInfo, NULL);
4703 __EXCEPT_PAGE_FAULT
4705 SetLastError(STATUS_ACCESS_VIOLATION);
4707 __ENDTRY
4708 TRACE("returning %d\n", ret);
4709 return ret;
4712 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
4713 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4715 BOOL ret;
4716 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4717 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
4718 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
4719 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4721 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4722 pvStructInfo, *pcbStructInfo, pcbDecoded);
4724 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4725 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4726 array ? array->rgItems : NULL);
4727 return ret;
4730 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4731 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4732 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4734 BOOL ret = FALSE;
4735 struct AsnDecodeSequenceItem items[] = {
4736 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4737 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4738 /* Placeholder for the hash algorithms - redundant with those in the
4739 * signers, so just ignore them.
4741 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4742 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4743 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4744 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4745 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4746 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4747 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4748 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4749 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4750 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4751 sizeof(struct GenericArray), TRUE, TRUE,
4752 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4753 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4754 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4755 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4758 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4759 pDecodePara, signedInfo, *pcbSignedInfo);
4761 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4762 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
4763 NULL, NULL);
4764 TRACE("returning %d\n", ret);
4765 return ret;
4768 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4769 LPCSTR lpszStructType)
4771 CryptDecodeObjectExFunc decodeFunc = NULL;
4773 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4774 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4776 SetLastError(ERROR_FILE_NOT_FOUND);
4777 return NULL;
4779 if (!HIWORD(lpszStructType))
4781 switch (LOWORD(lpszStructType))
4783 case LOWORD(X509_CERT):
4784 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4785 break;
4786 case LOWORD(X509_CERT_TO_BE_SIGNED):
4787 decodeFunc = CRYPT_AsnDecodeCert;
4788 break;
4789 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4790 decodeFunc = CRYPT_AsnDecodeCRL;
4791 break;
4792 case LOWORD(X509_EXTENSIONS):
4793 decodeFunc = CRYPT_AsnDecodeExtensions;
4794 break;
4795 case LOWORD(X509_NAME_VALUE):
4796 decodeFunc = CRYPT_AsnDecodeNameValue;
4797 break;
4798 case LOWORD(X509_NAME):
4799 decodeFunc = CRYPT_AsnDecodeName;
4800 break;
4801 case LOWORD(X509_PUBLIC_KEY_INFO):
4802 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4803 break;
4804 case LOWORD(X509_AUTHORITY_KEY_ID):
4805 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4806 break;
4807 case LOWORD(X509_ALTERNATE_NAME):
4808 decodeFunc = CRYPT_AsnDecodeAltName;
4809 break;
4810 case LOWORD(X509_BASIC_CONSTRAINTS):
4811 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4812 break;
4813 case LOWORD(X509_BASIC_CONSTRAINTS2):
4814 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4815 break;
4816 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4817 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4818 break;
4819 case LOWORD(X509_UNICODE_NAME):
4820 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4821 break;
4822 case LOWORD(PKCS_ATTRIBUTE):
4823 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4824 break;
4825 case LOWORD(X509_UNICODE_NAME_VALUE):
4826 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4827 break;
4828 case LOWORD(X509_OCTET_STRING):
4829 decodeFunc = CRYPT_AsnDecodeOctets;
4830 break;
4831 case LOWORD(X509_BITS):
4832 case LOWORD(X509_KEY_USAGE):
4833 decodeFunc = CRYPT_AsnDecodeBits;
4834 break;
4835 case LOWORD(X509_INTEGER):
4836 decodeFunc = CRYPT_AsnDecodeInt;
4837 break;
4838 case LOWORD(X509_MULTI_BYTE_INTEGER):
4839 decodeFunc = CRYPT_AsnDecodeInteger;
4840 break;
4841 case LOWORD(X509_MULTI_BYTE_UINT):
4842 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4843 break;
4844 case LOWORD(X509_ENUMERATED):
4845 decodeFunc = CRYPT_AsnDecodeEnumerated;
4846 break;
4847 case LOWORD(X509_CHOICE_OF_TIME):
4848 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4849 break;
4850 case LOWORD(X509_AUTHORITY_KEY_ID2):
4851 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4852 break;
4853 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4854 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
4855 break;
4856 case LOWORD(PKCS_CONTENT_INFO):
4857 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4858 break;
4859 case LOWORD(X509_SEQUENCE_OF_ANY):
4860 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4861 break;
4862 case LOWORD(PKCS_UTC_TIME):
4863 decodeFunc = CRYPT_AsnDecodeUtcTime;
4864 break;
4865 case LOWORD(X509_CRL_DIST_POINTS):
4866 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4867 break;
4868 case LOWORD(X509_ENHANCED_KEY_USAGE):
4869 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4870 break;
4871 case LOWORD(PKCS_CTL):
4872 decodeFunc = CRYPT_AsnDecodeCTL;
4873 break;
4874 case LOWORD(PKCS_SMIME_CAPABILITIES):
4875 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
4876 break;
4877 case LOWORD(PKCS_ATTRIBUTES):
4878 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4879 break;
4880 case LOWORD(X509_ISSUING_DIST_POINT):
4881 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4882 break;
4883 case LOWORD(X509_NAME_CONSTRAINTS):
4884 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4885 break;
4886 case LOWORD(PKCS7_SIGNER_INFO):
4887 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4888 break;
4889 case LOWORD(CMS_SIGNER_INFO):
4890 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
4891 break;
4894 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4895 decodeFunc = CRYPT_AsnDecodeExtensions;
4896 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4897 decodeFunc = CRYPT_AsnDecodeUtcTime;
4898 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4899 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
4900 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4901 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4902 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4903 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4904 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4905 decodeFunc = CRYPT_AsnDecodeEnumerated;
4906 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4907 decodeFunc = CRYPT_AsnDecodeBits;
4908 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4909 decodeFunc = CRYPT_AsnDecodeOctets;
4910 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4911 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4912 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4913 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4914 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4915 decodeFunc = CRYPT_AsnDecodeAltName;
4916 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4917 decodeFunc = CRYPT_AsnDecodeAltName;
4918 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4919 decodeFunc = CRYPT_AsnDecodeAltName;
4920 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4921 decodeFunc = CRYPT_AsnDecodeAltName;
4922 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4923 decodeFunc = CRYPT_AsnDecodeAltName;
4924 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4925 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4926 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4927 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4928 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4929 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4930 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4931 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4932 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4933 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
4934 else if (!strcmp(lpszStructType, szOID_CTL))
4935 decodeFunc = CRYPT_AsnDecodeCTL;
4936 return decodeFunc;
4939 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4940 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4942 static HCRYPTOIDFUNCSET set = NULL;
4943 CryptDecodeObjectFunc decodeFunc = NULL;
4945 if (!set)
4946 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4947 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4948 (void **)&decodeFunc, hFunc);
4949 return decodeFunc;
4952 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4953 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4955 static HCRYPTOIDFUNCSET set = NULL;
4956 CryptDecodeObjectExFunc decodeFunc = NULL;
4958 if (!set)
4959 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4960 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4961 (void **)&decodeFunc, hFunc);
4962 return decodeFunc;
4965 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4966 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4967 DWORD *pcbStructInfo)
4969 BOOL ret = FALSE;
4970 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4971 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4972 HCRYPTOIDFUNCADDR hFunc = NULL;
4974 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4975 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4976 pvStructInfo, pcbStructInfo);
4978 if (!pvStructInfo && !pcbStructInfo)
4980 SetLastError(ERROR_INVALID_PARAMETER);
4981 return FALSE;
4983 if (cbEncoded > MAX_ENCODED_LEN)
4985 SetLastError(CRYPT_E_ASN1_LARGE);
4986 return FALSE;
4989 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4990 lpszStructType)))
4992 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4993 debugstr_a(lpszStructType));
4994 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4995 lpszStructType, &hFunc);
4996 if (!pCryptDecodeObject)
4997 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4998 lpszStructType, &hFunc);
5000 if (pCryptDecodeObject)
5001 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5002 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5003 else if (pCryptDecodeObjectEx)
5004 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
5005 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
5006 pvStructInfo, pcbStructInfo);
5007 if (hFunc)
5008 CryptFreeOIDFunctionAddress(hFunc, 0);
5009 TRACE_(crypt)("returning %d\n", ret);
5010 return ret;
5013 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5014 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5015 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5017 BOOL ret = FALSE;
5018 CryptDecodeObjectExFunc decodeFunc;
5019 HCRYPTOIDFUNCADDR hFunc = NULL;
5021 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
5022 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5023 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5025 if (!pvStructInfo && !pcbStructInfo)
5027 SetLastError(ERROR_INVALID_PARAMETER);
5028 return FALSE;
5030 if (cbEncoded > MAX_ENCODED_LEN)
5032 SetLastError(CRYPT_E_ASN1_LARGE);
5033 return FALSE;
5036 SetLastError(NOERROR);
5037 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5038 *(BYTE **)pvStructInfo = NULL;
5039 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
5040 if (!decodeFunc)
5042 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5043 debugstr_a(lpszStructType));
5044 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
5045 &hFunc);
5047 if (decodeFunc)
5048 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5049 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5050 else
5052 CryptDecodeObjectFunc pCryptDecodeObject =
5053 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
5055 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
5056 * directly, as that could cause an infinite loop.
5058 if (pCryptDecodeObject)
5060 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5062 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5063 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
5064 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5065 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
5066 ret = pCryptDecodeObject(dwCertEncodingType,
5067 lpszStructType, pbEncoded, cbEncoded, dwFlags,
5068 *(BYTE **)pvStructInfo, pcbStructInfo);
5070 else
5071 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5072 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5075 if (hFunc)
5076 CryptFreeOIDFunctionAddress(hFunc, 0);
5077 TRACE_(crypt)("returning %d\n", ret);
5078 return ret;