msvcrt/tests: Remove a space before a '\n'.
[wine/gsoc-2012-control.git] / dlls / crypt32 / decode.c
blobcda8b62aed17f53258b0b6cf96ce1c4fbfd05875
1 /*
2 * Copyright 2005-2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
33 #include "config.h"
34 #include "wine/port.h"
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
41 #define NONAMELESSUNION
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "winnls.h"
47 #include "snmp.h"
48 #include "wine/debug.h"
49 #include "wine/exception.h"
50 #include "crypt32_private.h"
52 /* This is a bit arbitrary, but to set some limit: */
53 #define MAX_ENCODED_LEN 0x02000000
55 #define ASN_FLAGS_MASK 0xe0
56 #define ASN_TYPE_MASK 0x1f
58 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
59 WINE_DECLARE_DEBUG_CHANNEL(crypt);
61 struct GenericArray
63 DWORD cItems;
64 BYTE *rgItems;
67 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
68 DWORD, DWORD, void *, DWORD *);
69 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
70 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
72 /* Internal decoders don't do memory allocation or exception handling, and
73 * they report how many bytes they decoded.
75 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
76 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
78 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
79 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
80 DWORD *pcbDecoded);
81 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
82 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
83 DWORD *pcbDecoded);
84 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
85 * time, doesn't do memory allocation, and doesn't do exception handling.
87 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
88 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
89 DWORD *pcbDecoded);
90 /* Assumes algo->Parameters.pbData is set ahead of time. */
91 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
92 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
93 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
94 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
97 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
98 DWORD *pcbDecoded);
99 /* Doesn't check the tag, assumes the caller does so */
100 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
101 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
102 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
103 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
104 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
105 * member has been initialized, doesn't do exception handling, and doesn't do
106 * memory allocation. Also doesn't check tag, assumes the caller has checked
107 * it.
109 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
110 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
111 DWORD *pcbDecoded);
112 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
113 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
114 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
115 DWORD *pcbDecoded);
116 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
117 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
118 DWORD *pcbDecoded);
120 /* Gets the number of length bytes from the given (leading) length byte */
121 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
123 /* Helper function to get the encoded length of the data starting at pbEncoded,
124 * where pbEncoded[0] is the tag. If the data are too short to contain a
125 * length or if the length is too large for cbEncoded, sets an appropriate
126 * error code and returns FALSE. If the encoded length is unknown due to
127 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
129 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
130 DWORD *len)
132 BOOL ret;
134 if (cbEncoded <= 1)
136 SetLastError(CRYPT_E_ASN1_CORRUPT);
137 ret = FALSE;
139 else if (pbEncoded[1] <= 0x7f)
141 if (pbEncoded[1] + 1 > cbEncoded)
143 SetLastError(CRYPT_E_ASN1_EOD);
144 ret = FALSE;
146 else
148 *len = pbEncoded[1];
149 ret = TRUE;
152 else if (pbEncoded[1] == 0x80)
154 *len = CMSG_INDEFINITE_LENGTH;
155 ret = TRUE;
157 else
159 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
161 if (lenLen > sizeof(DWORD) + 1)
163 SetLastError(CRYPT_E_ASN1_LARGE);
164 ret = FALSE;
166 else if (lenLen + 2 > cbEncoded)
168 SetLastError(CRYPT_E_ASN1_CORRUPT);
169 ret = FALSE;
171 else
173 DWORD out = 0;
175 pbEncoded += 2;
176 while (--lenLen)
178 out <<= 8;
179 out |= *pbEncoded++;
181 if (out + lenLen + 1 > cbEncoded)
183 SetLastError(CRYPT_E_ASN1_EOD);
184 ret = FALSE;
186 else
188 *len = out;
189 ret = TRUE;
193 return ret;
196 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
197 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
199 BOOL ret;
201 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
202 *len == CMSG_INDEFINITE_LENGTH)
204 SetLastError(CRYPT_E_ASN1_CORRUPT);
205 ret = FALSE;
207 return ret;
210 /* Helper function to check *pcbStructInfo, set it to the required size, and
211 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
212 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
213 * pointer to the newly allocated memory.
215 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
216 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
217 DWORD bytesNeeded)
219 BOOL ret = TRUE;
221 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
223 if (pDecodePara && pDecodePara->pfnAlloc)
224 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
225 else
226 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
227 if (!*(BYTE **)pvStructInfo)
228 ret = FALSE;
229 else
230 *pcbStructInfo = bytesNeeded;
232 else if (*pcbStructInfo < bytesNeeded)
234 *pcbStructInfo = bytesNeeded;
235 SetLastError(ERROR_MORE_DATA);
236 ret = FALSE;
238 else
239 *pcbStructInfo = bytesNeeded;
240 return ret;
243 static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
245 if (pDecodePara && pDecodePara->pfnFree)
246 pDecodePara->pfnFree(pv);
247 else
248 LocalFree(pv);
251 /* Helper function to check *pcbStructInfo and set it to the required size.
252 * Assumes pvStructInfo is not NULL.
254 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
256 BOOL ret;
258 if (*pcbStructInfo < bytesNeeded)
260 *pcbStructInfo = bytesNeeded;
261 SetLastError(ERROR_MORE_DATA);
262 ret = FALSE;
264 else
266 *pcbStructInfo = bytesNeeded;
267 ret = TRUE;
269 return ret;
272 /* tag:
273 * The expected tag of the item. If tag is 0, decodeFunc is called
274 * regardless of the tag value seen.
275 * offset:
276 * A sequence is decoded into a struct. The offset member is the
277 * offset of this item within that struct.
278 * decodeFunc:
279 * The decoder function to use. If this is NULL, then the member isn't
280 * decoded, but minSize space is reserved for it.
281 * minSize:
282 * The minimum amount of space occupied after decoding. You must set this.
283 * optional:
284 * If true, and the tag doesn't match the expected tag for this item,
285 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
286 * filled with 0 for this member.
287 * hasPointer, pointerOffset:
288 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
289 * the offset within the struct of the data pointer (or to the
290 * first data pointer, if more than one exist).
291 * size:
292 * Used by CRYPT_AsnDecodeSequence, not for your use.
294 struct AsnDecodeSequenceItem
296 BYTE tag;
297 DWORD offset;
298 InternalDecodeFunc decodeFunc;
299 DWORD minSize;
300 BOOL optional;
301 BOOL hasPointer;
302 DWORD pointerOffset;
303 DWORD size;
306 /* Decodes the items in a sequence, where the items are described in items,
307 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
308 * pvStructInfo. nextData is a pointer to the memory location at which the
309 * first decoded item with a dynamic pointer should point.
310 * Upon decoding, *cbDecoded is the total number of bytes decoded.
311 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
313 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
314 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
315 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
317 BOOL ret;
318 DWORD i, decoded = 0;
319 const BYTE *ptr = pbEncoded;
321 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
322 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
324 for (i = 0, ret = TRUE; ret && i < cItem; i++)
326 if (cbEncoded - (ptr - pbEncoded) != 0)
328 DWORD itemLen;
330 if ((ret = CRYPT_GetLengthIndefinite(ptr,
331 cbEncoded - (ptr - pbEncoded), &itemLen)))
333 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
335 if (ptr[0] == items[i].tag || !items[i].tag)
337 DWORD itemEncodedLen;
339 if (itemLen == CMSG_INDEFINITE_LENGTH)
340 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
341 else
342 itemEncodedLen = 1 + itemLenBytes + itemLen;
343 if (nextData && pvStructInfo && items[i].hasPointer)
345 TRACE("Setting next pointer to %p\n",
346 nextData);
347 *(BYTE **)((BYTE *)pvStructInfo +
348 items[i].pointerOffset) = nextData;
350 if (items[i].decodeFunc)
352 DWORD itemDecoded;
354 if (pvStructInfo)
355 TRACE("decoding item %d\n", i);
356 else
357 TRACE("sizing item %d\n", i);
358 ret = items[i].decodeFunc(ptr, itemEncodedLen,
359 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
360 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
361 : NULL, &items[i].size, &itemDecoded);
362 if (ret)
364 /* Account for alignment padding */
365 items[i].size = ALIGN_DWORD_PTR(items[i].size);
366 TRACE("item %d size: %d\n", i, items[i].size);
367 if (nextData && items[i].hasPointer &&
368 items[i].size > items[i].minSize)
369 nextData += items[i].size - items[i].minSize;
370 if (itemDecoded > itemEncodedLen)
372 WARN("decoded length %d exceeds encoded %d\n",
373 itemDecoded, itemEncodedLen);
374 SetLastError(CRYPT_E_ASN1_CORRUPT);
375 ret = FALSE;
377 else
379 ptr += itemDecoded;
380 decoded += itemDecoded;
381 TRACE("item %d: decoded %d bytes\n", i,
382 itemDecoded);
385 else if (items[i].optional &&
386 GetLastError() == CRYPT_E_ASN1_BADTAG)
388 TRACE("skipping optional item %d\n", i);
389 items[i].size = items[i].minSize;
390 SetLastError(NOERROR);
391 ret = TRUE;
393 else
394 TRACE("item %d failed: %08x\n", i,
395 GetLastError());
397 else if (itemLen == CMSG_INDEFINITE_LENGTH)
399 ERR("can't use indefinite length encoding without a decoder\n");
400 SetLastError(CRYPT_E_ASN1_CORRUPT);
401 ret = FALSE;
403 else
405 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
406 ptr += itemEncodedLen;
407 decoded += itemEncodedLen;
408 items[i].size = items[i].minSize;
411 else if (items[i].optional)
413 TRACE("skipping optional item %d\n", i);
414 items[i].size = items[i].minSize;
416 else
418 TRACE("item %d: tag %02x doesn't match expected %02x\n",
419 i, ptr[0], items[i].tag);
420 SetLastError(CRYPT_E_ASN1_BADTAG);
421 ret = FALSE;
425 else if (items[i].optional)
427 TRACE("missing optional item %d, skipping\n", i);
428 items[i].size = items[i].minSize;
430 else
432 TRACE("not enough bytes for item %d, failing\n", i);
433 SetLastError(CRYPT_E_ASN1_CORRUPT);
434 ret = FALSE;
437 if (cbDecoded)
438 *cbDecoded = decoded;
439 TRACE("returning %d\n", ret);
440 return ret;
443 /* This decodes an arbitrary sequence into a contiguous block of memory
444 * (basically, a struct.) Each element being decoded is described by a struct
445 * AsnDecodeSequenceItem, see above.
446 * startingPointer is an optional pointer to the first place where dynamic
447 * data will be stored. If you know the starting offset, you may pass it
448 * here. Otherwise, pass NULL, and one will be inferred from the items.
450 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
451 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
452 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
453 DWORD *pcbDecoded, void *startingPointer)
455 BOOL ret;
457 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
458 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
459 startingPointer);
461 if (!cbEncoded)
463 SetLastError(CRYPT_E_ASN1_EOD);
464 return FALSE;
466 if (pbEncoded[0] == ASN_SEQUENCE)
468 DWORD dataLen;
470 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
472 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
473 const BYTE *ptr = pbEncoded + 1 + lenBytes;
474 BOOL indefinite = FALSE;
476 cbEncoded -= 1 + lenBytes;
477 if (dataLen == CMSG_INDEFINITE_LENGTH)
479 dataLen = cbEncoded;
480 indefinite = TRUE;
482 else if (cbEncoded < dataLen)
484 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
485 cbEncoded);
486 SetLastError(CRYPT_E_ASN1_CORRUPT);
487 ret = FALSE;
489 if (ret)
491 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
492 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
493 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
495 if (cbDecoded > cbEncoded - 2)
497 /* Not enough space for 0 TLV */
498 SetLastError(CRYPT_E_ASN1_CORRUPT);
499 ret = FALSE;
501 else if (*(ptr + cbDecoded) != 0 ||
502 *(ptr + cbDecoded + 1) != 0)
504 TRACE("expected 0 TLV\n");
505 SetLastError(CRYPT_E_ASN1_CORRUPT);
506 ret = FALSE;
508 else
509 cbDecoded += 2;
512 if (ret && !indefinite && cbDecoded != dataLen)
514 TRACE("expected %d decoded, got %d, failing\n", dataLen,
515 cbDecoded);
516 SetLastError(CRYPT_E_ASN1_CORRUPT);
517 ret = FALSE;
519 if (ret)
521 DWORD i, bytesNeeded = 0, structSize = 0;
523 for (i = 0; i < cItem; i++)
525 bytesNeeded += items[i].size;
526 structSize += items[i].minSize;
528 if (pcbDecoded)
529 *pcbDecoded = 1 + lenBytes + cbDecoded;
530 if (!pvStructInfo)
531 *pcbStructInfo = bytesNeeded;
532 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
533 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
535 BYTE *nextData;
537 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
538 pvStructInfo = *(BYTE **)pvStructInfo;
539 if (startingPointer)
540 nextData = startingPointer;
541 else
542 nextData = (BYTE *)pvStructInfo + structSize;
543 memset(pvStructInfo, 0, structSize);
544 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
545 ptr, dataLen, dwFlags, pvStructInfo, nextData,
546 &cbDecoded);
547 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
548 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
553 else
555 SetLastError(CRYPT_E_ASN1_BADTAG);
556 ret = FALSE;
558 TRACE("returning %d (%08x)\n", ret, GetLastError());
559 return ret;
562 /* tag:
563 * The expected tag of the entire encoded array (usually a variant
564 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
565 * regardless of the tag seen.
566 * decodeFunc:
567 * used to decode each item in the array
568 * itemSize:
569 * is the minimum size of each decoded item
570 * hasPointer:
571 * indicates whether each item has a dynamic pointer
572 * pointerOffset:
573 * indicates the offset within itemSize at which the pointer exists
575 struct AsnArrayDescriptor
577 BYTE tag;
578 InternalDecodeFunc decodeFunc;
579 DWORD itemSize;
580 BOOL hasPointer;
581 DWORD pointerOffset;
584 struct AsnArrayItemSize
586 DWORD encodedLen;
587 DWORD size;
590 /* Decodes an array of like types into a struct GenericArray.
591 * The layout and decoding of the array are described by a struct
592 * AsnArrayDescriptor.
594 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
595 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
596 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
597 DWORD *pcbDecoded, void *startingPointer)
599 BOOL ret = TRUE;
601 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
602 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
603 startingPointer);
605 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
607 DWORD dataLen;
609 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
611 DWORD bytesNeeded, cItems = 0, decoded;
612 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
613 /* There can be arbitrarily many items, but there is often only one.
615 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
617 decoded = 1 + lenBytes;
618 bytesNeeded = sizeof(struct GenericArray);
619 if (dataLen)
621 const BYTE *ptr;
622 BOOL doneDecoding = FALSE;
624 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
626 if (dataLen == CMSG_INDEFINITE_LENGTH)
628 if (ptr[0] == 0)
630 doneDecoding = TRUE;
631 if (ptr[1] != 0)
633 SetLastError(CRYPT_E_ASN1_CORRUPT);
634 ret = FALSE;
636 else
637 decoded += 2;
640 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
641 doneDecoding = TRUE;
642 if (!doneDecoding)
644 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
646 /* Each item decoded may not tolerate extraneous bytes,
647 * so get the length of the next element if known.
649 if ((ret = CRYPT_GetLengthIndefinite(ptr,
650 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
652 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
653 itemEncoded = cbEncoded - (ptr - pbEncoded);
654 else
655 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
656 itemDataLen;
658 if (ret)
659 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
660 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
661 &itemDecoded);
662 if (ret)
664 cItems++;
665 if (itemSizes != &itemSize)
666 itemSizes = CryptMemRealloc(itemSizes,
667 cItems * sizeof(struct AsnArrayItemSize));
668 else if (cItems > 1)
670 itemSizes =
671 CryptMemAlloc(
672 cItems * sizeof(struct AsnArrayItemSize));
673 if (itemSizes)
674 memcpy(itemSizes, &itemSize,
675 sizeof(itemSize));
677 if (itemSizes)
679 decoded += itemDecoded;
680 itemSizes[cItems - 1].encodedLen = itemEncoded;
681 itemSizes[cItems - 1].size = size;
682 bytesNeeded += size;
683 ptr += itemEncoded;
685 else
686 ret = FALSE;
691 if (ret)
693 if (pcbDecoded)
694 *pcbDecoded = decoded;
695 if (!pvStructInfo)
696 *pcbStructInfo = bytesNeeded;
697 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
698 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
700 DWORD i;
701 BYTE *nextData;
702 const BYTE *ptr;
703 struct GenericArray *array;
705 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
706 pvStructInfo = *(BYTE **)pvStructInfo;
707 array = pvStructInfo;
708 array->cItems = cItems;
709 if (startingPointer)
710 array->rgItems = startingPointer;
711 else
712 array->rgItems = (BYTE *)array +
713 sizeof(struct GenericArray);
714 nextData = array->rgItems +
715 array->cItems * arrayDesc->itemSize;
716 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
717 i < cItems && ptr - pbEncoded - 1 - lenBytes <
718 dataLen; i++)
720 DWORD itemDecoded;
722 if (arrayDesc->hasPointer)
723 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
724 + arrayDesc->pointerOffset) = nextData;
725 ret = arrayDesc->decodeFunc(ptr,
726 itemSizes[i].encodedLen,
727 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
728 array->rgItems + i * arrayDesc->itemSize,
729 &itemSizes[i].size, &itemDecoded);
730 if (ret)
732 nextData += itemSizes[i].size - arrayDesc->itemSize;
733 ptr += itemDecoded;
736 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
737 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
740 if (itemSizes != &itemSize)
741 CryptMemFree(itemSizes);
744 else
746 SetLastError(CRYPT_E_ASN1_BADTAG);
747 ret = FALSE;
749 return ret;
752 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
753 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
754 * to CRYPT_E_ASN1_CORRUPT.
755 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
756 * set!
758 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
759 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
761 BOOL ret;
762 DWORD dataLen;
764 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
766 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
767 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
769 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
770 bytesNeeded += 1 + lenBytes + dataLen;
772 if (pcbDecoded)
773 *pcbDecoded = 1 + lenBytes + dataLen;
774 if (!pvStructInfo)
775 *pcbStructInfo = bytesNeeded;
776 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
778 CRYPT_DER_BLOB *blob;
780 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
781 pvStructInfo = *(BYTE **)pvStructInfo;
782 blob = pvStructInfo;
783 blob->cbData = 1 + lenBytes + dataLen;
784 if (blob->cbData)
786 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
787 blob->pbData = (BYTE *)pbEncoded;
788 else
790 assert(blob->pbData);
791 memcpy(blob->pbData, pbEncoded, blob->cbData);
794 else
796 SetLastError(CRYPT_E_ASN1_CORRUPT);
797 ret = FALSE;
801 return ret;
804 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
805 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
806 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
807 DWORD *pcbDecoded)
809 BOOL ret;
811 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
812 pvStructInfo, *pcbStructInfo, pcbDecoded);
814 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
815 * place.
817 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
818 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
819 pcbDecoded);
820 if (ret && pvStructInfo)
822 CRYPT_BIT_BLOB *blob = pvStructInfo;
824 if (blob->cbData)
826 DWORD i;
827 BYTE temp;
829 for (i = 0; i < blob->cbData / 2; i++)
831 temp = blob->pbData[i];
832 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
833 blob->pbData[blob->cbData - i - 1] = temp;
837 TRACE("returning %d (%08x)\n", ret, GetLastError());
838 return ret;
841 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
842 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
843 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
845 BOOL ret = TRUE;
847 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
848 pDecodePara, pvStructInfo, *pcbStructInfo);
850 __TRY
852 struct AsnDecodeSequenceItem items[] = {
853 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
854 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
855 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
856 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
857 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
858 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
859 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
860 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
861 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
862 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
865 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
866 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
867 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
868 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
869 pcbStructInfo, NULL, NULL);
871 __EXCEPT_PAGE_FAULT
873 SetLastError(STATUS_ACCESS_VIOLATION);
874 ret = FALSE;
876 __ENDTRY
878 TRACE("Returning %d (%08x)\n", ret, GetLastError());
879 return ret;
882 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
883 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
885 BOOL ret;
886 DWORD dataLen;
888 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
890 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
892 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
893 dwFlags, pvStructInfo, pcbStructInfo, NULL);
894 if (pcbDecoded)
895 *pcbDecoded = 1 + lenBytes + dataLen;
897 return ret;
900 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
901 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
903 BOOL ret;
905 struct AsnDecodeSequenceItem items[] = {
906 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
907 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
908 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
909 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
912 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
913 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
914 pcbDecoded, NULL);
915 return ret;
918 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
919 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
920 DWORD *pcbDecoded)
922 BOOL ret;
923 DWORD dataLen;
925 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
927 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
929 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
930 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
931 if (ret && pcbDecoded)
932 *pcbDecoded = 1 + lenBytes + dataLen;
934 return ret;
937 static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
938 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
939 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
941 BOOL ret = TRUE;
942 struct AsnDecodeSequenceItem items[] = {
943 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
944 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
945 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
946 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
947 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
948 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
949 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
950 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
951 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
952 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
953 Issuer.pbData) },
954 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
955 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
956 FALSE, 0 },
957 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
958 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
959 Subject.pbData) },
960 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
961 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
962 FALSE, TRUE, offsetof(CERT_INFO,
963 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
964 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
965 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
966 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
967 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
968 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
969 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
970 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
971 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
972 offsetof(CERT_INFO, rgExtension), 0 },
975 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
976 pDecodePara, pvStructInfo, *pcbStructInfo);
978 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
979 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
980 NULL, NULL);
981 if (ret && pvStructInfo)
983 CERT_INFO *info;
985 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
986 info = *(CERT_INFO **)pvStructInfo;
987 else
988 info = pvStructInfo;
989 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
990 !info->Subject.cbData)
992 SetLastError(CRYPT_E_ASN1_CORRUPT);
993 /* Don't need to deallocate, because it should have failed on the
994 * first pass (and no memory was allocated.)
996 ret = FALSE;
1000 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1001 return ret;
1004 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1005 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1006 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1008 BOOL ret = FALSE;
1010 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1011 pDecodePara, pvStructInfo, *pcbStructInfo);
1013 __TRY
1015 DWORD size = 0;
1017 /* Unless told not to, first try to decode it as a signed cert. */
1018 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1020 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1022 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1023 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1024 &signedCert, &size);
1025 if (ret)
1027 size = 0;
1028 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1029 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1030 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1031 pvStructInfo, pcbStructInfo);
1032 LocalFree(signedCert);
1035 /* Failing that, try it as an unsigned cert */
1036 if (!ret)
1038 size = 0;
1039 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1040 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1041 pDecodePara, pvStructInfo, pcbStructInfo);
1044 __EXCEPT_PAGE_FAULT
1046 SetLastError(STATUS_ACCESS_VIOLATION);
1048 __ENDTRY
1050 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1051 return ret;
1054 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1055 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1057 BOOL ret;
1058 struct AsnDecodeSequenceItem items[] = {
1059 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1060 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1061 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1062 { 0, offsetof(CRL_ENTRY, RevocationDate),
1063 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1064 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1065 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1066 offsetof(CRL_ENTRY, rgExtension), 0 },
1068 PCRL_ENTRY entry = pvStructInfo;
1070 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1071 *pcbStructInfo);
1073 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1074 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1075 entry ? entry->SerialNumber.pbData : NULL);
1076 if (ret && entry && !entry->SerialNumber.cbData)
1078 WARN("empty CRL entry serial number\n");
1079 SetLastError(CRYPT_E_ASN1_CORRUPT);
1080 ret = FALSE;
1082 return ret;
1085 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1086 * been set prior to calling.
1088 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1089 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1091 BOOL ret;
1092 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1093 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1094 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1095 struct GenericArray *entries = pvStructInfo;
1097 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1098 pvStructInfo, *pcbStructInfo, pcbDecoded);
1100 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1101 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1102 entries ? entries->rgItems : NULL);
1103 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1104 return ret;
1107 static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1108 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1109 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1111 struct AsnDecodeSequenceItem items[] = {
1112 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1113 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1114 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1115 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1116 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1117 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1118 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1119 Issuer.pbData) },
1120 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1121 sizeof(FILETIME), FALSE, FALSE, 0 },
1122 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1123 sizeof(FILETIME), TRUE, FALSE, 0 },
1124 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1125 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1126 offsetof(CRL_INFO, rgCRLEntry), 0 },
1127 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1128 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1129 offsetof(CRL_INFO, rgExtension), 0 },
1131 BOOL ret = TRUE;
1133 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1134 pDecodePara, pvStructInfo, *pcbStructInfo);
1136 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1137 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1138 NULL, NULL);
1140 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1141 return ret;
1144 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1145 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1146 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1148 BOOL ret = FALSE;
1150 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1151 pDecodePara, pvStructInfo, *pcbStructInfo);
1153 __TRY
1155 DWORD size = 0;
1157 /* Unless told not to, first try to decode it as a signed crl. */
1158 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1160 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1162 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1163 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1164 &signedCrl, &size);
1165 if (ret)
1167 size = 0;
1168 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1169 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1170 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1171 pvStructInfo, pcbStructInfo);
1172 LocalFree(signedCrl);
1175 /* Failing that, try it as an unsigned crl */
1176 if (!ret)
1178 size = 0;
1179 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1180 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1181 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1184 __EXCEPT_PAGE_FAULT
1186 SetLastError(STATUS_ACCESS_VIOLATION);
1188 __ENDTRY
1190 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1191 return ret;
1194 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1195 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1197 BOOL ret = TRUE;
1198 DWORD dataLen;
1200 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1201 pvStructInfo, *pcbStructInfo);
1203 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1205 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1206 DWORD bytesNeeded = sizeof(LPSTR);
1208 if (dataLen)
1210 /* The largest possible string for the first two components
1211 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1213 char firstTwo[6];
1214 const BYTE *ptr;
1216 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1217 pbEncoded[1 + lenBytes] / 40,
1218 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1219 * 40);
1220 bytesNeeded += strlen(firstTwo) + 1;
1221 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1222 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1224 /* large enough for ".4000000" */
1225 char str[9];
1226 int val = 0;
1228 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1229 (*ptr & 0x80))
1231 val <<= 7;
1232 val |= *ptr & 0x7f;
1233 ptr++;
1235 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1236 (*ptr & 0x80))
1238 SetLastError(CRYPT_E_ASN1_CORRUPT);
1239 ret = FALSE;
1241 else
1243 val <<= 7;
1244 val |= *ptr++;
1245 snprintf(str, sizeof(str), ".%d", val);
1246 bytesNeeded += strlen(str);
1250 if (pcbDecoded)
1251 *pcbDecoded = 1 + lenBytes + dataLen;
1252 if (!pvStructInfo)
1253 *pcbStructInfo = bytesNeeded;
1254 else if (*pcbStructInfo < bytesNeeded)
1256 *pcbStructInfo = bytesNeeded;
1257 SetLastError(ERROR_MORE_DATA);
1258 ret = FALSE;
1260 else
1262 if (dataLen)
1264 const BYTE *ptr;
1265 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1267 *pszObjId = 0;
1268 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1269 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1270 40) * 40);
1271 pszObjId += strlen(pszObjId);
1272 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1273 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1275 int val = 0;
1277 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1278 (*ptr & 0x80))
1280 val <<= 7;
1281 val |= *ptr & 0x7f;
1282 ptr++;
1284 val <<= 7;
1285 val |= *ptr++;
1286 sprintf(pszObjId, ".%d", val);
1287 pszObjId += strlen(pszObjId);
1290 else
1291 *(LPSTR *)pvStructInfo = NULL;
1292 *pcbStructInfo = bytesNeeded;
1295 return ret;
1298 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1299 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1301 BOOL ret;
1303 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1304 pvStructInfo, *pcbStructInfo);
1306 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1307 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1308 pvStructInfo, pcbStructInfo, pcbDecoded);
1309 else
1311 SetLastError(CRYPT_E_ASN1_BADTAG);
1312 ret = FALSE;
1314 return ret;
1317 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1318 * ahead of time!
1320 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1321 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1323 struct AsnDecodeSequenceItem items[] = {
1324 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1325 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1326 offsetof(CERT_EXTENSION, pszObjId), 0 },
1327 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1328 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1329 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1330 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1331 offsetof(CERT_EXTENSION, Value.pbData) },
1333 BOOL ret = TRUE;
1334 PCERT_EXTENSION ext = pvStructInfo;
1336 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1337 *pcbStructInfo);
1339 if (ext)
1340 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1341 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1342 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1343 pcbDecoded, ext ? ext->pszObjId : NULL);
1344 if (ext)
1345 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1346 debugstr_a(ext->pszObjId));
1347 TRACE("returning %d (%08x)\n", ret, GetLastError());
1348 return ret;
1351 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1352 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1353 DWORD *pcbDecoded)
1355 BOOL ret = TRUE;
1356 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1357 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1358 offsetof(CERT_EXTENSION, pszObjId) };
1359 PCERT_EXTENSIONS exts = pvStructInfo;
1361 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1362 pvStructInfo, *pcbStructInfo, pcbDecoded);
1364 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1365 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1366 exts ? exts->rgExtension : NULL);
1367 return ret;
1370 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1371 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1372 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1374 BOOL ret = TRUE;
1376 __TRY
1378 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1379 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1380 if (ret && pvStructInfo)
1382 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1383 pcbStructInfo, *pcbStructInfo);
1384 if (ret)
1386 CERT_EXTENSIONS *exts;
1388 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1389 pvStructInfo = *(BYTE **)pvStructInfo;
1390 exts = pvStructInfo;
1391 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1392 sizeof(CERT_EXTENSIONS));
1393 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1394 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1395 pcbStructInfo, NULL);
1399 __EXCEPT_PAGE_FAULT
1401 SetLastError(STATUS_ACCESS_VIOLATION);
1402 ret = FALSE;
1404 __ENDTRY
1405 return ret;
1408 /* Warning: this assumes the address of value->Value.pbData is already set, in
1409 * order to avoid overwriting memory. (In some cases, it may change it, if it
1410 * doesn't copy anything to memory.) Be sure to set it correctly!
1412 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1413 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1414 DWORD *pcbDecoded)
1416 BOOL ret = TRUE;
1417 DWORD dataLen;
1418 CERT_NAME_VALUE *value = pvStructInfo;
1420 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1422 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1423 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1425 switch (pbEncoded[0])
1427 case ASN_OCTETSTRING:
1428 valueType = CERT_RDN_OCTET_STRING;
1429 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1430 bytesNeeded += dataLen;
1431 break;
1432 case ASN_NUMERICSTRING:
1433 valueType = CERT_RDN_NUMERIC_STRING;
1434 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1435 bytesNeeded += dataLen;
1436 break;
1437 case ASN_PRINTABLESTRING:
1438 valueType = CERT_RDN_PRINTABLE_STRING;
1439 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1440 bytesNeeded += dataLen;
1441 break;
1442 case ASN_IA5STRING:
1443 valueType = CERT_RDN_IA5_STRING;
1444 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1445 bytesNeeded += dataLen;
1446 break;
1447 case ASN_T61STRING:
1448 valueType = CERT_RDN_T61_STRING;
1449 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1450 bytesNeeded += dataLen;
1451 break;
1452 case ASN_VIDEOTEXSTRING:
1453 valueType = CERT_RDN_VIDEOTEX_STRING;
1454 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1455 bytesNeeded += dataLen;
1456 break;
1457 case ASN_GRAPHICSTRING:
1458 valueType = CERT_RDN_GRAPHIC_STRING;
1459 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1460 bytesNeeded += dataLen;
1461 break;
1462 case ASN_VISIBLESTRING:
1463 valueType = CERT_RDN_VISIBLE_STRING;
1464 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1465 bytesNeeded += dataLen;
1466 break;
1467 case ASN_GENERALSTRING:
1468 valueType = CERT_RDN_GENERAL_STRING;
1469 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1470 bytesNeeded += dataLen;
1471 break;
1472 case ASN_UNIVERSALSTRING:
1473 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1474 SetLastError(CRYPT_E_ASN1_BADTAG);
1475 return FALSE;
1476 case ASN_BMPSTRING:
1477 valueType = CERT_RDN_BMP_STRING;
1478 bytesNeeded += dataLen;
1479 break;
1480 case ASN_UTF8STRING:
1481 valueType = CERT_RDN_UTF8_STRING;
1482 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1483 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1484 break;
1485 default:
1486 SetLastError(CRYPT_E_ASN1_BADTAG);
1487 return FALSE;
1490 if (pcbDecoded)
1491 *pcbDecoded = 1 + lenBytes + dataLen;
1492 if (!value)
1493 *pcbStructInfo = bytesNeeded;
1494 else if (*pcbStructInfo < bytesNeeded)
1496 *pcbStructInfo = bytesNeeded;
1497 SetLastError(ERROR_MORE_DATA);
1498 ret = FALSE;
1500 else
1502 *pcbStructInfo = bytesNeeded;
1503 value->dwValueType = valueType;
1504 if (dataLen)
1506 DWORD i;
1508 assert(value->Value.pbData);
1509 switch (pbEncoded[0])
1511 case ASN_OCTETSTRING:
1512 case ASN_NUMERICSTRING:
1513 case ASN_PRINTABLESTRING:
1514 case ASN_IA5STRING:
1515 case ASN_T61STRING:
1516 case ASN_VIDEOTEXSTRING:
1517 case ASN_GRAPHICSTRING:
1518 case ASN_VISIBLESTRING:
1519 case ASN_GENERALSTRING:
1520 value->Value.cbData = dataLen;
1521 if (dataLen)
1523 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1524 memcpy(value->Value.pbData,
1525 pbEncoded + 1 + lenBytes, dataLen);
1526 else
1527 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1528 lenBytes;
1530 break;
1531 case ASN_BMPSTRING:
1533 LPWSTR str = (LPWSTR)value->Value.pbData;
1535 value->Value.cbData = dataLen;
1536 for (i = 0; i < dataLen / 2; i++)
1537 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1538 pbEncoded[1 + lenBytes + 2 * i + 1];
1539 break;
1541 case ASN_UTF8STRING:
1543 LPWSTR str = (LPWSTR)value->Value.pbData;
1545 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1546 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1547 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1548 break;
1552 else
1554 value->Value.cbData = 0;
1555 value->Value.pbData = NULL;
1559 return ret;
1562 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1563 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1564 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1566 BOOL ret = TRUE;
1568 __TRY
1570 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1571 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1572 if (ret && pvStructInfo)
1574 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1575 pcbStructInfo, *pcbStructInfo);
1576 if (ret)
1578 CERT_NAME_VALUE *value;
1580 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1581 pvStructInfo = *(BYTE **)pvStructInfo;
1582 value = pvStructInfo;
1583 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1584 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1585 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1586 pcbStructInfo, NULL);
1590 __EXCEPT_PAGE_FAULT
1592 SetLastError(STATUS_ACCESS_VIOLATION);
1593 ret = FALSE;
1595 __ENDTRY
1596 return ret;
1599 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1600 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1601 DWORD *pcbDecoded)
1603 BOOL ret = TRUE;
1604 DWORD dataLen;
1605 CERT_NAME_VALUE *value = pvStructInfo;
1607 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1609 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1610 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1612 switch (pbEncoded[0])
1614 case ASN_NUMERICSTRING:
1615 valueType = CERT_RDN_NUMERIC_STRING;
1616 if (dataLen)
1617 bytesNeeded += (dataLen + 1) * 2;
1618 break;
1619 case ASN_PRINTABLESTRING:
1620 valueType = CERT_RDN_PRINTABLE_STRING;
1621 if (dataLen)
1622 bytesNeeded += (dataLen + 1) * 2;
1623 break;
1624 case ASN_IA5STRING:
1625 valueType = CERT_RDN_IA5_STRING;
1626 if (dataLen)
1627 bytesNeeded += (dataLen + 1) * 2;
1628 break;
1629 case ASN_T61STRING:
1630 valueType = CERT_RDN_T61_STRING;
1631 if (dataLen)
1632 bytesNeeded += (dataLen + 1) * 2;
1633 break;
1634 case ASN_VIDEOTEXSTRING:
1635 valueType = CERT_RDN_VIDEOTEX_STRING;
1636 if (dataLen)
1637 bytesNeeded += (dataLen + 1) * 2;
1638 break;
1639 case ASN_GRAPHICSTRING:
1640 valueType = CERT_RDN_GRAPHIC_STRING;
1641 if (dataLen)
1642 bytesNeeded += (dataLen + 1) * 2;
1643 break;
1644 case ASN_VISIBLESTRING:
1645 valueType = CERT_RDN_VISIBLE_STRING;
1646 if (dataLen)
1647 bytesNeeded += (dataLen + 1) * 2;
1648 break;
1649 case ASN_GENERALSTRING:
1650 valueType = CERT_RDN_GENERAL_STRING;
1651 if (dataLen)
1652 bytesNeeded += (dataLen + 1) * 2;
1653 break;
1654 case ASN_UNIVERSALSTRING:
1655 valueType = CERT_RDN_UNIVERSAL_STRING;
1656 if (dataLen)
1657 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
1658 break;
1659 case ASN_BMPSTRING:
1660 valueType = CERT_RDN_BMP_STRING;
1661 if (dataLen)
1662 bytesNeeded += dataLen + sizeof(WCHAR);
1663 break;
1664 case ASN_UTF8STRING:
1665 valueType = CERT_RDN_UTF8_STRING;
1666 if (dataLen)
1667 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
1668 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
1669 break;
1670 default:
1671 SetLastError(CRYPT_E_ASN1_BADTAG);
1672 return FALSE;
1675 if (pcbDecoded)
1676 *pcbDecoded = 1 + lenBytes + dataLen;
1677 if (!value)
1678 *pcbStructInfo = bytesNeeded;
1679 else if (*pcbStructInfo < bytesNeeded)
1681 *pcbStructInfo = bytesNeeded;
1682 SetLastError(ERROR_MORE_DATA);
1683 ret = FALSE;
1685 else
1687 *pcbStructInfo = bytesNeeded;
1688 value->dwValueType = valueType;
1689 if (dataLen)
1691 DWORD i;
1692 LPWSTR str = (LPWSTR)value->Value.pbData;
1694 assert(value->Value.pbData);
1695 switch (pbEncoded[0])
1697 case ASN_NUMERICSTRING:
1698 case ASN_PRINTABLESTRING:
1699 case ASN_IA5STRING:
1700 case ASN_T61STRING:
1701 case ASN_VIDEOTEXSTRING:
1702 case ASN_GRAPHICSTRING:
1703 case ASN_VISIBLESTRING:
1704 case ASN_GENERALSTRING:
1705 value->Value.cbData = dataLen * 2;
1706 for (i = 0; i < dataLen; i++)
1707 str[i] = pbEncoded[1 + lenBytes + i];
1708 str[i] = 0;
1709 break;
1710 case ASN_UNIVERSALSTRING:
1711 value->Value.cbData = dataLen / 2;
1712 for (i = 0; i < dataLen / 4; i++)
1713 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1714 | pbEncoded[1 + lenBytes + 2 * i + 3];
1715 str[i] = 0;
1716 break;
1717 case ASN_BMPSTRING:
1718 value->Value.cbData = dataLen;
1719 for (i = 0; i < dataLen / 2; i++)
1720 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1721 pbEncoded[1 + lenBytes + 2 * i + 1];
1722 str[i] = 0;
1723 break;
1724 case ASN_UTF8STRING:
1725 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1726 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1727 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1728 value->Value.pbData[value->Value.cbData / sizeof(WCHAR)]
1729 = 0;
1730 value->Value.cbData += sizeof(WCHAR);
1731 break;
1734 else
1736 value->Value.cbData = 0;
1737 value->Value.pbData = NULL;
1741 return ret;
1744 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1745 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1746 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1748 BOOL ret = TRUE;
1750 __TRY
1752 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1753 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1754 if (ret && pvStructInfo)
1756 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1757 pcbStructInfo, *pcbStructInfo);
1758 if (ret)
1760 CERT_NAME_VALUE *value;
1762 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1763 pvStructInfo = *(BYTE **)pvStructInfo;
1764 value = pvStructInfo;
1765 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1766 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1767 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1768 pcbStructInfo, NULL);
1772 __EXCEPT_PAGE_FAULT
1774 SetLastError(STATUS_ACCESS_VIOLATION);
1775 ret = FALSE;
1777 __ENDTRY
1778 return ret;
1781 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1782 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1784 BOOL ret;
1785 struct AsnDecodeSequenceItem items[] = {
1786 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1787 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1788 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1789 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1790 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1791 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1793 CERT_RDN_ATTR *attr = pvStructInfo;
1795 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1796 pvStructInfo, *pcbStructInfo);
1798 if (attr)
1799 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1800 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1801 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1802 attr ? attr->pszObjId : NULL);
1803 if (attr)
1805 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1806 debugstr_a(attr->pszObjId));
1807 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1809 TRACE("returning %d (%08x)\n", ret, GetLastError());
1810 return ret;
1813 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1814 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1816 BOOL ret = TRUE;
1817 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1818 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1819 offsetof(CERT_RDN_ATTR, pszObjId) };
1820 PCERT_RDN rdn = pvStructInfo;
1822 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1823 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1824 rdn ? rdn->rgRDNAttr : NULL);
1825 return ret;
1828 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1829 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1830 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1832 BOOL ret = TRUE;
1834 __TRY
1836 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1837 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1838 offsetof(CERT_RDN, rgRDNAttr) };
1840 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1841 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1843 __EXCEPT_PAGE_FAULT
1845 SetLastError(STATUS_ACCESS_VIOLATION);
1846 ret = FALSE;
1848 __ENDTRY
1849 return ret;
1852 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1853 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1854 DWORD *pcbDecoded)
1856 BOOL ret;
1857 struct AsnDecodeSequenceItem items[] = {
1858 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1859 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1860 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1861 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1862 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1863 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1865 CERT_RDN_ATTR *attr = pvStructInfo;
1867 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1868 pvStructInfo, *pcbStructInfo);
1870 if (attr)
1871 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1872 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1873 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1874 attr ? attr->pszObjId : NULL);
1875 if (attr)
1877 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1878 debugstr_a(attr->pszObjId));
1879 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1881 TRACE("returning %d (%08x)\n", ret, GetLastError());
1882 return ret;
1885 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1886 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1888 BOOL ret = TRUE;
1889 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1890 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1891 offsetof(CERT_RDN_ATTR, pszObjId) };
1892 PCERT_RDN rdn = pvStructInfo;
1894 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1895 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1896 rdn ? rdn->rgRDNAttr : NULL);
1897 return ret;
1900 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1901 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1902 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1904 BOOL ret = TRUE;
1906 __TRY
1908 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1909 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1910 offsetof(CERT_RDN, rgRDNAttr) };
1912 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1913 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1915 __EXCEPT_PAGE_FAULT
1917 SetLastError(STATUS_ACCESS_VIOLATION);
1918 ret = FALSE;
1920 __ENDTRY
1921 return ret;
1924 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1925 DWORD *pcbDecoded)
1927 BOOL ret = TRUE, done = FALSE;
1928 DWORD indefiniteNestingLevels = 0, decoded = 0;
1930 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1932 do {
1933 DWORD dataLen;
1935 if (!cbEncoded)
1936 done = TRUE;
1937 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
1938 &dataLen)))
1940 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1942 if (dataLen == CMSG_INDEFINITE_LENGTH)
1944 indefiniteNestingLevels++;
1945 pbEncoded += 1 + lenBytes;
1946 cbEncoded -= 1 + lenBytes;
1947 decoded += 1 + lenBytes;
1948 TRACE("indefiniteNestingLevels = %d\n",
1949 indefiniteNestingLevels);
1951 else
1953 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
1954 indefiniteNestingLevels)
1956 indefiniteNestingLevels--;
1957 TRACE("indefiniteNestingLevels = %d\n",
1958 indefiniteNestingLevels);
1960 pbEncoded += 1 + lenBytes + dataLen;
1961 cbEncoded -= 1 + lenBytes + dataLen;
1962 decoded += 1 + lenBytes + dataLen;
1963 if (!indefiniteNestingLevels)
1964 done = TRUE;
1967 } while (ret && !done);
1968 /* If we haven't found all 0 TLVs, we haven't found the end */
1969 if (ret && indefiniteNestingLevels)
1971 SetLastError(CRYPT_E_ASN1_EOD);
1972 ret = FALSE;
1974 if (ret)
1975 *pcbDecoded = decoded;
1976 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
1977 return ret;
1980 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1981 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1982 DWORD *pcbDecoded)
1984 BOOL ret = TRUE;
1985 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
1987 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1988 pvStructInfo, *pcbStructInfo);
1990 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
1992 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1993 bytesNeeded += encodedLen;
1994 if (!pvStructInfo)
1995 *pcbStructInfo = bytesNeeded;
1996 else if (*pcbStructInfo < bytesNeeded)
1998 SetLastError(ERROR_MORE_DATA);
1999 *pcbStructInfo = bytesNeeded;
2000 ret = FALSE;
2002 else
2004 PCRYPT_OBJID_BLOB blob = pvStructInfo;
2006 *pcbStructInfo = bytesNeeded;
2007 blob->cbData = encodedLen;
2008 if (encodedLen)
2010 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2011 blob->pbData = (LPBYTE)pbEncoded;
2012 else
2014 assert(blob->pbData);
2015 memcpy(blob->pbData, pbEncoded, blob->cbData);
2018 else
2019 blob->pbData = NULL;
2021 if (pcbDecoded)
2022 *pcbDecoded = encodedLen;
2024 return ret;
2027 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
2028 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2030 BOOL ret;
2031 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
2032 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2033 struct GenericArray *array = pvStructInfo;
2035 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2036 pvStructInfo, *pcbStructInfo, pcbDecoded);
2038 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2039 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2040 array ? array->rgItems : NULL);
2041 return ret;
2044 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2045 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2047 BOOL ret;
2048 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2049 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2050 CTL_USAGE *usage = pvStructInfo;
2052 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2053 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2054 usage ? usage->rgpszUsageIdentifier : NULL);
2055 return ret;
2058 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2059 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2061 struct AsnDecodeSequenceItem items[] = {
2062 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2063 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2064 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2065 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2066 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), FALSE,
2067 TRUE, offsetof(CTL_ENTRY, rgAttribute), 0 },
2069 BOOL ret = TRUE;
2070 CTL_ENTRY *entry = pvStructInfo;
2072 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2073 *pcbStructInfo);
2075 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2076 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2077 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2078 return ret;
2081 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2082 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2084 BOOL ret;
2085 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2086 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2087 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2088 struct GenericArray *entries = pvStructInfo;
2090 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2091 pvStructInfo, *pcbStructInfo, pcbDecoded);
2093 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2094 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2095 entries ? entries->rgItems : NULL);
2096 return ret;
2099 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2100 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2101 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2103 BOOL ret = FALSE;
2105 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2106 pDecodePara, pvStructInfo, *pcbStructInfo);
2108 __TRY
2110 struct AsnDecodeSequenceItem items[] = {
2111 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2112 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2113 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2114 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2115 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2116 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2117 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
2118 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2119 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2120 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2121 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2122 { 0, offsetof(CTL_INFO, ThisUpdate),
2123 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2124 0 },
2125 { 0, offsetof(CTL_INFO, NextUpdate),
2126 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2127 0 },
2128 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2129 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2130 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2131 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2132 CRYPT_AsnDecodeCTLEntries, sizeof(struct GenericArray),
2133 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2134 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2135 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
2136 offsetof(CTL_INFO, rgExtension), 0 },
2139 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2140 pDecodePara, pvStructInfo, *pcbStructInfo);
2142 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2143 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2144 pcbStructInfo, NULL, NULL);
2146 __EXCEPT_PAGE_FAULT
2148 SetLastError(STATUS_ACCESS_VIOLATION);
2150 __ENDTRY
2151 return ret;
2154 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2155 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2156 DWORD *pcbDecoded)
2158 BOOL ret;
2159 struct AsnDecodeSequenceItem items[] = {
2160 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2161 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2162 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2163 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2164 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2165 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2167 PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
2169 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2170 pvStructInfo, *pcbStructInfo);
2172 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2173 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2174 pcbDecoded, capability ? capability->pszObjId : NULL);
2175 TRACE("returning %d\n", ret);
2176 return ret;
2179 static BOOL CRYPT_AsnDecodeSMIMECapabilitiesInternal(const BYTE *pbEncoded,
2180 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2181 DWORD *pcbDecoded)
2183 struct AsnArrayDescriptor arrayDesc = { 0,
2184 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2185 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2186 PCRYPT_SMIME_CAPABILITIES capabilities = pvStructInfo;
2187 BOOL ret;
2189 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2190 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2191 capabilities ? capabilities->rgCapability : NULL);
2192 return ret;
2195 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2196 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2197 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2199 BOOL ret = FALSE;
2201 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2202 pDecodePara, pvStructInfo, *pcbStructInfo);
2204 __TRY
2206 DWORD bytesNeeded;
2208 if (!cbEncoded)
2209 SetLastError(CRYPT_E_ASN1_EOD);
2210 else if (pbEncoded[0] != ASN_SEQUENCEOF)
2211 SetLastError(CRYPT_E_ASN1_CORRUPT);
2212 else if ((ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
2213 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2214 NULL)))
2216 if (!pvStructInfo)
2217 *pcbStructInfo = bytesNeeded;
2218 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2219 pvStructInfo, pcbStructInfo, bytesNeeded)))
2221 PCRYPT_SMIME_CAPABILITIES capabilities;
2223 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2224 pvStructInfo = *(BYTE **)pvStructInfo;
2225 capabilities = pvStructInfo;
2226 capabilities->rgCapability =
2227 (PCRYPT_SMIME_CAPABILITY)((BYTE *)pvStructInfo +
2228 sizeof(CRYPT_SMIME_CAPABILITIES));
2229 ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
2230 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2231 &bytesNeeded, NULL);
2235 __EXCEPT_PAGE_FAULT
2237 SetLastError(STATUS_ACCESS_VIOLATION);
2239 __ENDTRY
2240 TRACE("returning %d\n", ret);
2241 return ret;
2244 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
2245 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2246 DWORD *pcbDecoded)
2248 BOOL ret = TRUE;
2249 DWORD dataLen;
2250 LPSTR *pStr = pvStructInfo;
2252 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2254 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2255 DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
2257 if (pbEncoded[0] != ASN_IA5STRING)
2259 SetLastError(CRYPT_E_ASN1_CORRUPT);
2260 ret = FALSE;
2262 else
2264 bytesNeeded += dataLen;
2265 if (pcbDecoded)
2266 *pcbDecoded = 1 + lenBytes + dataLen;
2267 if (!pvStructInfo)
2268 *pcbStructInfo = bytesNeeded;
2269 else if (*pcbStructInfo < bytesNeeded)
2271 *pcbStructInfo = bytesNeeded;
2272 SetLastError(ERROR_MORE_DATA);
2273 ret = FALSE;
2275 else
2277 *pcbStructInfo = bytesNeeded;
2278 if (dataLen)
2280 LPSTR str = *pStr;
2282 assert(str);
2283 memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
2284 str[dataLen] = 0;
2286 else
2287 *pStr = NULL;
2291 return ret;
2294 static BOOL CRYPT_AsnDecodeIntArray(const BYTE *pbEncoded,
2295 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2296 DWORD *pcbDecoded)
2298 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2299 CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
2300 struct GenericArray *array = pvStructInfo;
2301 BOOL ret;
2303 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2304 pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
2306 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2307 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2308 array ? array->rgItems : NULL);
2309 TRACE("returning %d\n", ret);
2310 return ret;
2313 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
2314 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2315 DWORD *pcbDecoded)
2317 BOOL ret;
2318 struct AsnDecodeSequenceItem items[] = {
2319 { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2320 pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
2321 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
2322 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2323 cNoticeNumbers), CRYPT_AsnDecodeIntArray, sizeof(struct GenericArray),
2324 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2325 rgNoticeNumbers), 0 },
2327 DWORD bytesNeeded;
2329 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2330 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2332 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2333 pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
2334 NULL);
2335 if (ret)
2337 /* The caller is expecting a pointer to a
2338 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
2339 * CRYPT_AsnDecodeSequence is decoding a
2340 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. Increment the bytes
2341 * needed, and decode again if the requisite space is available.
2343 bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
2344 if (!pvStructInfo)
2345 *pcbStructInfo = bytesNeeded;
2346 else if (*pcbStructInfo < bytesNeeded)
2348 *pcbStructInfo = bytesNeeded;
2349 SetLastError(ERROR_MORE_DATA);
2350 ret = FALSE;
2352 else
2354 PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
2356 *pcbStructInfo = bytesNeeded;
2357 /* The pointer (pvStructInfo) passed in points to the first dynamic
2358 * pointer, so use it as the pointer to the
2359 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
2360 * appropriate offset for the first dynamic pointer within the
2361 * notice reference by pointing to the first memory location past
2362 * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
2364 noticeRef =
2365 *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
2366 noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
2367 sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
2368 ret = CRYPT_AsnDecodeSequence(items,
2369 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2370 NULL, noticeRef, &bytesNeeded, pcbDecoded,
2371 noticeRef->pszOrganization);
2374 TRACE("returning %d\n", ret);
2375 return ret;
2378 static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
2379 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2380 DWORD *pcbDecoded)
2382 BOOL ret = TRUE;
2383 DWORD dataLen;
2385 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2387 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2388 DWORD bytesNeeded = sizeof(LPWSTR);
2390 switch (pbEncoded[0])
2392 case ASN_NUMERICSTRING:
2393 if (dataLen)
2394 bytesNeeded += (dataLen + 1) * 2;
2395 break;
2396 case ASN_PRINTABLESTRING:
2397 if (dataLen)
2398 bytesNeeded += (dataLen + 1) * 2;
2399 break;
2400 case ASN_IA5STRING:
2401 if (dataLen)
2402 bytesNeeded += (dataLen + 1) * 2;
2403 break;
2404 case ASN_T61STRING:
2405 if (dataLen)
2406 bytesNeeded += (dataLen + 1) * 2;
2407 break;
2408 case ASN_VIDEOTEXSTRING:
2409 if (dataLen)
2410 bytesNeeded += (dataLen + 1) * 2;
2411 break;
2412 case ASN_GRAPHICSTRING:
2413 if (dataLen)
2414 bytesNeeded += (dataLen + 1) * 2;
2415 break;
2416 case ASN_VISIBLESTRING:
2417 if (dataLen)
2418 bytesNeeded += (dataLen + 1) * 2;
2419 break;
2420 case ASN_GENERALSTRING:
2421 if (dataLen)
2422 bytesNeeded += (dataLen + 1) * 2;
2423 break;
2424 case ASN_UNIVERSALSTRING:
2425 if (dataLen)
2426 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
2427 break;
2428 case ASN_BMPSTRING:
2429 if (dataLen)
2430 bytesNeeded += dataLen + sizeof(WCHAR);
2431 break;
2432 case ASN_UTF8STRING:
2433 if (dataLen)
2434 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
2435 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
2436 break;
2437 default:
2438 SetLastError(CRYPT_E_ASN1_BADTAG);
2439 return FALSE;
2442 if (pcbDecoded)
2443 *pcbDecoded = 1 + lenBytes + dataLen;
2444 if (!pvStructInfo)
2445 *pcbStructInfo = bytesNeeded;
2446 else if (*pcbStructInfo < bytesNeeded)
2448 *pcbStructInfo = bytesNeeded;
2449 SetLastError(ERROR_MORE_DATA);
2450 ret = FALSE;
2452 else
2454 LPWSTR *pStr = pvStructInfo;
2456 *pcbStructInfo = bytesNeeded;
2457 if (dataLen)
2459 DWORD i;
2460 LPWSTR str = *(LPWSTR *)pStr;
2462 assert(str);
2463 switch (pbEncoded[0])
2465 case ASN_NUMERICSTRING:
2466 case ASN_PRINTABLESTRING:
2467 case ASN_IA5STRING:
2468 case ASN_T61STRING:
2469 case ASN_VIDEOTEXSTRING:
2470 case ASN_GRAPHICSTRING:
2471 case ASN_VISIBLESTRING:
2472 case ASN_GENERALSTRING:
2473 for (i = 0; i < dataLen; i++)
2474 str[i] = pbEncoded[1 + lenBytes + i];
2475 str[i] = 0;
2476 break;
2477 case ASN_UNIVERSALSTRING:
2478 for (i = 0; i < dataLen / 4; i++)
2479 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2480 | pbEncoded[1 + lenBytes + 2 * i + 3];
2481 str[i] = 0;
2482 break;
2483 case ASN_BMPSTRING:
2484 for (i = 0; i < dataLen / 2; i++)
2485 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2486 pbEncoded[1 + lenBytes + 2 * i + 1];
2487 str[i] = 0;
2488 break;
2489 case ASN_UTF8STRING:
2491 int len = MultiByteToWideChar(CP_UTF8, 0,
2492 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2493 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
2494 str[len] = 0;
2495 break;
2499 else
2500 *pStr = NULL;
2503 return ret;
2506 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2507 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2508 DWORD *pcbStructInfo, DWORD *pcbDecoded)
2510 BOOL ret;
2511 struct AsnDecodeSequenceItem items[] = {
2512 { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2513 pNoticeReference), CRYPT_AsnDecodeNoticeReference,
2514 sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
2515 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
2516 { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
2517 CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
2518 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
2520 PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
2522 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2523 pvStructInfo, *pcbStructInfo);
2525 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2526 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2527 pcbDecoded, notice ? notice->pNoticeReference : NULL);
2528 TRACE("returning %d\n", ret);
2529 return ret;
2532 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
2533 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2534 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2535 void *pvStructInfo, DWORD *pcbStructInfo)
2537 BOOL ret = FALSE;
2539 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2540 pDecodePara, pvStructInfo, *pcbStructInfo);
2542 __TRY
2544 DWORD bytesNeeded;
2546 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
2547 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2548 NULL);
2549 if (ret)
2551 if (!pvStructInfo)
2552 *pcbStructInfo = bytesNeeded;
2553 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2554 pvStructInfo, pcbStructInfo, bytesNeeded)))
2556 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
2558 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2559 pvStructInfo = *(BYTE **)pvStructInfo;
2560 notice = pvStructInfo;
2561 notice->pNoticeReference =
2562 (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
2563 ((BYTE *)pvStructInfo +
2564 sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
2565 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2566 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
2567 pvStructInfo, &bytesNeeded, NULL);
2571 __EXCEPT_PAGE_FAULT
2573 SetLastError(STATUS_ACCESS_VIOLATION);
2575 __ENDTRY
2576 TRACE("returning %d\n", ret);
2577 return ret;
2580 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2581 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2582 DWORD *pcbDecoded)
2584 BOOL ret;
2585 struct AsnDecodeSequenceItem items[] = {
2586 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2587 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2588 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2589 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2590 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
2591 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2593 PCRYPT_ATTRIBUTE attr = pvStructInfo;
2595 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2596 pvStructInfo, *pcbStructInfo);
2598 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2599 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2600 pcbDecoded, attr ? attr->pszObjId : NULL);
2601 TRACE("returning %d\n", ret);
2602 return ret;
2605 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2606 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2607 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2609 BOOL ret = FALSE;
2611 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2612 pDecodePara, pvStructInfo, *pcbStructInfo);
2614 __TRY
2616 DWORD bytesNeeded;
2618 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2619 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2620 if (ret)
2622 if (!pvStructInfo)
2623 *pcbStructInfo = bytesNeeded;
2624 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2625 pvStructInfo, pcbStructInfo, bytesNeeded)))
2627 PCRYPT_ATTRIBUTE attr;
2629 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2630 pvStructInfo = *(BYTE **)pvStructInfo;
2631 attr = pvStructInfo;
2632 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2633 sizeof(CRYPT_ATTRIBUTE));
2634 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2635 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2636 NULL);
2640 __EXCEPT_PAGE_FAULT
2642 SetLastError(STATUS_ACCESS_VIOLATION);
2644 __ENDTRY
2645 TRACE("returning %d\n", ret);
2646 return ret;
2649 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2650 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2651 DWORD *pcbDecoded)
2653 struct AsnArrayDescriptor arrayDesc = { 0,
2654 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2655 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2656 PCRYPT_ATTRIBUTES attrs = pvStructInfo;
2657 BOOL ret;
2659 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2660 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2661 NULL);
2662 return ret;
2665 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2666 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2667 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2669 BOOL ret = FALSE;
2671 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2672 pDecodePara, pvStructInfo, *pcbStructInfo);
2674 __TRY
2676 DWORD bytesNeeded;
2678 if (!cbEncoded)
2679 SetLastError(CRYPT_E_ASN1_EOD);
2680 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2681 SetLastError(CRYPT_E_ASN1_CORRUPT);
2682 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2683 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2684 NULL)))
2686 if (!pvStructInfo)
2687 *pcbStructInfo = bytesNeeded;
2688 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2689 pvStructInfo, pcbStructInfo, bytesNeeded)))
2691 PCRYPT_ATTRIBUTES attrs;
2693 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2694 pvStructInfo = *(BYTE **)pvStructInfo;
2695 attrs = pvStructInfo;
2696 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2697 sizeof(CRYPT_ATTRIBUTES));
2698 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2699 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2700 &bytesNeeded, NULL);
2704 __EXCEPT_PAGE_FAULT
2706 SetLastError(STATUS_ACCESS_VIOLATION);
2708 __ENDTRY
2709 TRACE("returning %d\n", ret);
2710 return ret;
2713 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2714 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2716 CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
2717 BOOL ret = TRUE;
2718 struct AsnDecodeSequenceItem items[] = {
2719 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2720 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2721 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2722 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2723 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2724 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2727 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2728 pvStructInfo, *pcbStructInfo, pcbDecoded);
2730 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2731 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2732 pcbDecoded, algo ? algo->pszObjId : NULL);
2733 if (ret && pvStructInfo)
2735 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2736 debugstr_a(algo->pszObjId));
2738 return ret;
2741 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2742 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2743 DWORD *pcbDecoded)
2745 BOOL ret = TRUE;
2746 struct AsnDecodeSequenceItem items[] = {
2747 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2748 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2749 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2750 Algorithm.pszObjId) },
2751 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2752 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2753 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2755 PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
2757 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2758 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2759 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2760 return ret;
2763 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2764 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2765 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2767 BOOL ret = TRUE;
2769 __TRY
2771 DWORD bytesNeeded;
2773 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2774 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2776 if (!pvStructInfo)
2777 *pcbStructInfo = bytesNeeded;
2778 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2779 pvStructInfo, pcbStructInfo, bytesNeeded)))
2781 PCERT_PUBLIC_KEY_INFO info;
2783 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2784 pvStructInfo = *(BYTE **)pvStructInfo;
2785 info = pvStructInfo;
2786 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2787 sizeof(CERT_PUBLIC_KEY_INFO);
2788 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2789 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2790 &bytesNeeded, NULL);
2794 __EXCEPT_PAGE_FAULT
2796 SetLastError(STATUS_ACCESS_VIOLATION);
2797 ret = FALSE;
2799 __ENDTRY
2800 return ret;
2803 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2804 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2806 BOOL ret;
2808 if (cbEncoded < 3)
2810 SetLastError(CRYPT_E_ASN1_CORRUPT);
2811 return FALSE;
2813 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2815 SetLastError(CRYPT_E_ASN1_CORRUPT);
2816 return FALSE;
2818 if (pbEncoded[1] > 1)
2820 SetLastError(CRYPT_E_ASN1_CORRUPT);
2821 return FALSE;
2823 if (pcbDecoded)
2824 *pcbDecoded = 3;
2825 if (!pvStructInfo)
2827 *pcbStructInfo = sizeof(BOOL);
2828 ret = TRUE;
2830 else if (*pcbStructInfo < sizeof(BOOL))
2832 *pcbStructInfo = sizeof(BOOL);
2833 SetLastError(ERROR_MORE_DATA);
2834 ret = FALSE;
2836 else
2838 *pcbStructInfo = sizeof(BOOL);
2839 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2840 ret = TRUE;
2842 TRACE("returning %d (%08x)\n", ret, GetLastError());
2843 return ret;
2846 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2847 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2849 PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
2850 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2851 BOOL ret;
2853 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2854 pvStructInfo, *pcbStructInfo);
2856 if (cbEncoded < 2)
2858 SetLastError(CRYPT_E_ASN1_CORRUPT);
2859 return FALSE;
2861 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2862 if (1 + lenBytes > cbEncoded)
2864 SetLastError(CRYPT_E_ASN1_CORRUPT);
2865 return FALSE;
2867 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2869 switch (pbEncoded[0] & ASN_TYPE_MASK)
2871 case 1: /* rfc822Name */
2872 case 2: /* dNSName */
2873 case 6: /* uniformResourceIdentifier */
2874 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2875 break;
2876 case 4: /* directoryName */
2877 case 7: /* iPAddress */
2878 bytesNeeded += dataLen;
2879 break;
2880 case 8: /* registeredID */
2881 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2882 &dataLen, NULL);
2883 if (ret)
2885 /* FIXME: ugly, shouldn't need to know internals of OID decode
2886 * function to use it.
2888 bytesNeeded += dataLen - sizeof(LPSTR);
2890 break;
2891 case 0: /* otherName */
2892 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2893 SetLastError(CRYPT_E_ASN1_BADTAG);
2894 ret = FALSE;
2895 break;
2896 case 3: /* x400Address, unimplemented */
2897 case 5: /* ediPartyName, unimplemented */
2898 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2899 SetLastError(CRYPT_E_ASN1_BADTAG);
2900 ret = FALSE;
2901 break;
2902 default:
2903 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2904 SetLastError(CRYPT_E_ASN1_CORRUPT);
2905 ret = FALSE;
2907 if (ret)
2909 if (pcbDecoded)
2910 *pcbDecoded = 1 + lenBytes + dataLen;
2911 if (!entry)
2912 *pcbStructInfo = bytesNeeded;
2913 else if (*pcbStructInfo < bytesNeeded)
2915 *pcbStructInfo = bytesNeeded;
2916 SetLastError(ERROR_MORE_DATA);
2917 ret = FALSE;
2919 else
2921 *pcbStructInfo = bytesNeeded;
2922 /* MS used values one greater than the asn1 ones.. sigh */
2923 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
2924 switch (pbEncoded[0] & ASN_TYPE_MASK)
2926 case 1: /* rfc822Name */
2927 case 2: /* dNSName */
2928 case 6: /* uniformResourceIdentifier */
2930 DWORD i;
2932 for (i = 0; i < dataLen; i++)
2933 entry->u.pwszURL[i] =
2934 (WCHAR)pbEncoded[1 + lenBytes + i];
2935 entry->u.pwszURL[i] = 0;
2936 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2937 debugstr_w(entry->u.pwszURL));
2938 break;
2940 case 4: /* directoryName */
2941 /* The data are memory-equivalent with the IPAddress case,
2942 * fall-through
2944 case 7: /* iPAddress */
2945 /* The next data pointer is in the pwszURL spot, that is,
2946 * the first 4 bytes. Need to move it to the next spot.
2948 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2949 entry->u.IPAddress.cbData = dataLen;
2950 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2951 dataLen);
2952 break;
2953 case 8: /* registeredID */
2954 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2955 &entry->u.pszRegisteredID, &dataLen, NULL);
2956 break;
2961 return ret;
2964 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2965 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2966 DWORD *pcbDecoded)
2968 BOOL ret = TRUE;
2969 struct AsnArrayDescriptor arrayDesc = { 0,
2970 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2971 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2972 PCERT_ALT_NAME_INFO info = pvStructInfo;
2974 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2975 pvStructInfo, *pcbStructInfo, pcbDecoded);
2977 if (info)
2978 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2979 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2980 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2981 info ? info->rgAltEntry : NULL);
2982 return ret;
2985 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2986 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2987 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2988 DWORD *pcbDecoded)
2990 BOOL ret;
2992 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2993 pvStructInfo, *pcbStructInfo, pcbDecoded);
2995 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2996 * place.
2998 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2999 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
3000 pcbDecoded);
3001 if (ret && pvStructInfo)
3003 CRYPT_DATA_BLOB *blob = pvStructInfo;
3005 if (blob->cbData)
3007 DWORD i;
3008 BYTE temp;
3010 for (i = 0; i < blob->cbData / 2; i++)
3012 temp = blob->pbData[i];
3013 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
3014 blob->pbData[blob->cbData - i - 1] = temp;
3018 TRACE("returning %d (%08x)\n", ret, GetLastError());
3019 return ret;
3022 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
3023 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3024 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3026 BOOL ret;
3028 __TRY
3030 struct AsnDecodeSequenceItem items[] = {
3031 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
3032 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3033 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
3034 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3035 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
3036 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
3037 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
3038 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
3039 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3040 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3041 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
3044 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3045 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3046 pcbStructInfo, NULL, NULL);
3048 __EXCEPT_PAGE_FAULT
3050 SetLastError(STATUS_ACCESS_VIOLATION);
3051 ret = FALSE;
3053 __ENDTRY
3054 return ret;
3057 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
3058 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3059 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3061 BOOL ret;
3063 __TRY
3065 struct AsnDecodeSequenceItem items[] = {
3066 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
3067 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3068 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
3069 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3070 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
3071 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
3072 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3073 AuthorityCertIssuer.rgAltEntry), 0 },
3074 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3075 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3076 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3077 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3078 AuthorityCertSerialNumber.pbData), 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 CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
3095 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3096 DWORD *pcbDecoded)
3098 struct AsnDecodeSequenceItem items[] = {
3099 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
3100 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3101 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
3102 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
3103 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
3104 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
3106 CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
3108 return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3109 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3110 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
3113 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
3114 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3115 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3117 BOOL ret;
3119 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3120 pDecodePara, pvStructInfo, *pcbStructInfo);
3122 __TRY
3124 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3125 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
3126 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
3128 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3129 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3131 __EXCEPT_PAGE_FAULT
3133 SetLastError(STATUS_ACCESS_VIOLATION);
3134 ret = FALSE;
3136 __ENDTRY
3137 return ret;
3140 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
3141 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3143 BOOL ret;
3144 DWORD dataLen;
3146 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3147 pvStructInfo, *pcbStructInfo, pcbDecoded);
3149 /* The caller has already checked the tag, no need to check it again.
3150 * Check the outer length is valid:
3152 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
3154 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3155 DWORD innerLen;
3157 pbEncoded += 1 + lenBytes;
3158 cbEncoded -= 1 + lenBytes;
3159 if (dataLen == CMSG_INDEFINITE_LENGTH)
3160 cbEncoded -= 2; /* space for 0 TLV */
3161 /* Check the inner length is valid: */
3162 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
3164 DWORD decodedLen;
3166 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
3167 pvStructInfo, pcbStructInfo, &decodedLen);
3168 if (dataLen == CMSG_INDEFINITE_LENGTH)
3170 if (*(pbEncoded + decodedLen) != 0 ||
3171 *(pbEncoded + decodedLen + 1) != 0)
3173 TRACE("expected 0 TLV, got {%02x,%02x}\n",
3174 *(pbEncoded + decodedLen),
3175 *(pbEncoded + decodedLen + 1));
3176 SetLastError(CRYPT_E_ASN1_CORRUPT);
3177 ret = FALSE;
3179 else
3180 decodedLen += 2;
3182 if (ret && pcbDecoded)
3184 *pcbDecoded = 1 + lenBytes + decodedLen;
3185 TRACE("decoded %d bytes\n", *pcbDecoded);
3189 return ret;
3192 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
3193 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3194 DWORD *pcbDecoded)
3196 CRYPT_CONTENT_INFO *info = pvStructInfo;
3197 struct AsnDecodeSequenceItem items[] = {
3198 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
3199 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3200 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
3201 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
3202 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
3203 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
3204 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
3206 BOOL ret;
3208 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3209 pvStructInfo, *pcbStructInfo, pcbDecoded);
3211 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3212 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3213 pcbDecoded, info ? info->pszObjId : NULL);
3214 return ret;
3217 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
3218 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3219 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3221 BOOL ret = FALSE;
3223 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3224 pDecodePara, pvStructInfo, *pcbStructInfo);
3226 __TRY
3228 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
3229 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3230 if (ret && pvStructInfo)
3232 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3233 pcbStructInfo, *pcbStructInfo);
3234 if (ret)
3236 CRYPT_CONTENT_INFO *info;
3238 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3239 pvStructInfo = *(BYTE **)pvStructInfo;
3240 info = pvStructInfo;
3241 info->pszObjId = (LPSTR)((BYTE *)info +
3242 sizeof(CRYPT_CONTENT_INFO));
3243 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
3244 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3245 pcbStructInfo, NULL);
3249 __EXCEPT_PAGE_FAULT
3251 SetLastError(STATUS_ACCESS_VIOLATION);
3253 __ENDTRY
3254 return ret;
3257 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
3258 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3259 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
3261 BOOL ret;
3262 struct AsnDecodeSequenceItem items[] = {
3263 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
3264 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3265 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
3266 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3267 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
3268 0 },
3269 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
3270 CRYPT_AsnDecodePKCSContentInfoInternal,
3271 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
3272 ContentInfo.pszObjId), 0 },
3273 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
3274 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
3275 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
3278 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3279 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
3280 NULL, NULL);
3281 return ret;
3284 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
3285 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3286 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3288 BOOL ret = TRUE;
3290 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3291 pDecodePara, pvStructInfo, *pcbStructInfo);
3293 __TRY
3295 DWORD bytesNeeded;
3297 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3298 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3300 if (!pvStructInfo)
3301 *pcbStructInfo = bytesNeeded;
3302 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3303 pvStructInfo, pcbStructInfo, bytesNeeded)))
3305 CERT_ALT_NAME_INFO *name;
3307 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3308 pvStructInfo = *(BYTE **)pvStructInfo;
3309 name = pvStructInfo;
3310 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
3311 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
3312 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3313 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3314 &bytesNeeded, NULL);
3318 __EXCEPT_PAGE_FAULT
3320 SetLastError(STATUS_ACCESS_VIOLATION);
3321 ret = FALSE;
3323 __ENDTRY
3324 return ret;
3327 struct PATH_LEN_CONSTRAINT
3329 BOOL fPathLenConstraint;
3330 DWORD dwPathLenConstraint;
3333 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3334 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3335 DWORD *pcbDecoded)
3337 BOOL ret = TRUE;
3338 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3340 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3341 pvStructInfo, *pcbStructInfo, pcbDecoded);
3343 if (!pvStructInfo)
3345 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3346 &size, pcbDecoded);
3347 *pcbStructInfo = bytesNeeded;
3349 else if (*pcbStructInfo < bytesNeeded)
3351 SetLastError(ERROR_MORE_DATA);
3352 *pcbStructInfo = bytesNeeded;
3353 ret = FALSE;
3355 else
3357 struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
3359 *pcbStructInfo = bytesNeeded;
3360 size = sizeof(constraint->dwPathLenConstraint);
3361 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3362 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3363 if (ret)
3364 constraint->fPathLenConstraint = TRUE;
3365 TRACE("got an int, dwPathLenConstraint is %d\n",
3366 constraint->dwPathLenConstraint);
3368 TRACE("returning %d (%08x)\n", ret, GetLastError());
3369 return ret;
3372 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3373 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3374 DWORD *pcbDecoded)
3376 BOOL ret;
3377 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3378 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3379 offsetof(CERT_NAME_BLOB, pbData) };
3380 struct GenericArray *entries = pvStructInfo;
3382 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3383 pvStructInfo, *pcbStructInfo, pcbDecoded);
3385 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3386 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3387 entries ? entries->rgItems : NULL);
3388 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3389 return ret;
3392 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3393 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3394 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3396 BOOL ret;
3398 __TRY
3400 struct AsnDecodeSequenceItem items[] = {
3401 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3402 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3403 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3404 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3405 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3406 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3407 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3408 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3409 sizeof(struct GenericArray), TRUE, TRUE,
3410 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3413 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3414 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3415 pcbStructInfo, NULL, NULL);
3417 __EXCEPT_PAGE_FAULT
3419 SetLastError(STATUS_ACCESS_VIOLATION);
3420 ret = FALSE;
3422 __ENDTRY
3423 return ret;
3426 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3427 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3428 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3430 BOOL ret;
3432 __TRY
3434 struct AsnDecodeSequenceItem items[] = {
3435 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3436 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3437 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3438 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3439 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3442 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3443 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3444 pcbStructInfo, NULL, NULL);
3446 __EXCEPT_PAGE_FAULT
3448 SetLastError(STATUS_ACCESS_VIOLATION);
3449 ret = FALSE;
3451 __ENDTRY
3452 return ret;
3455 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
3456 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3457 DWORD *pcbDecoded)
3459 struct AsnDecodeSequenceItem items[] = {
3460 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
3461 pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3462 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
3463 0 },
3464 { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
3465 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3466 offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
3468 BOOL ret;
3469 CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
3471 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3472 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3474 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3475 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3476 pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
3477 return ret;
3480 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
3481 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3482 DWORD *pcbDecoded)
3484 BOOL ret;
3485 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3486 CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
3487 offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
3488 struct GenericArray *entries = pvStructInfo;
3490 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3491 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3493 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3494 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3495 entries ? entries->rgItems : NULL);
3496 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3497 return ret;
3500 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
3501 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3503 struct AsnDecodeSequenceItem items[] = {
3504 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
3505 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3506 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
3507 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3508 CRYPT_AsnDecodePolicyQualifiers, sizeof(struct GenericArray), TRUE,
3509 TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
3511 CERT_POLICY_INFO *info = pvStructInfo;
3512 BOOL ret;
3514 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3515 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3517 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3518 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3519 pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
3520 return ret;
3523 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
3524 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3525 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3527 BOOL ret = FALSE;
3529 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3530 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3532 __TRY
3534 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3535 CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
3536 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
3538 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3539 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3541 __EXCEPT_PAGE_FAULT
3543 SetLastError(STATUS_ACCESS_VIOLATION);
3545 __ENDTRY
3546 return ret;
3549 #define RSA1_MAGIC 0x31415352
3551 struct DECODED_RSA_PUB_KEY
3553 DWORD pubexp;
3554 CRYPT_INTEGER_BLOB modulus;
3557 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3558 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3559 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3561 BOOL ret;
3563 __TRY
3565 struct AsnDecodeSequenceItem items[] = {
3566 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3567 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3568 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3569 0 },
3570 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3571 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3573 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3574 DWORD size = 0;
3576 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3577 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3578 &size, NULL, NULL);
3579 if (ret)
3581 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3582 decodedKey->modulus.cbData;
3584 if (!pvStructInfo)
3586 *pcbStructInfo = bytesNeeded;
3587 ret = TRUE;
3589 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3590 pvStructInfo, pcbStructInfo, bytesNeeded)))
3592 BLOBHEADER *hdr;
3593 RSAPUBKEY *rsaPubKey;
3595 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3596 pvStructInfo = *(BYTE **)pvStructInfo;
3597 hdr = pvStructInfo;
3598 hdr->bType = PUBLICKEYBLOB;
3599 hdr->bVersion = CUR_BLOB_VERSION;
3600 hdr->reserved = 0;
3601 hdr->aiKeyAlg = CALG_RSA_KEYX;
3602 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3603 sizeof(BLOBHEADER));
3604 rsaPubKey->magic = RSA1_MAGIC;
3605 rsaPubKey->pubexp = decodedKey->pubexp;
3606 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3607 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3608 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3609 decodedKey->modulus.cbData);
3611 LocalFree(decodedKey);
3614 __EXCEPT_PAGE_FAULT
3616 SetLastError(STATUS_ACCESS_VIOLATION);
3617 ret = FALSE;
3619 __ENDTRY
3620 return ret;
3623 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
3624 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3625 DWORD *pcbDecoded)
3627 BOOL ret;
3628 DWORD bytesNeeded, dataLen;
3630 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3631 pvStructInfo, *pcbStructInfo, pcbDecoded);
3633 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3635 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3637 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3638 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
3639 else
3640 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
3641 if (pcbDecoded)
3642 *pcbDecoded = 1 + lenBytes + dataLen;
3643 if (!pvStructInfo)
3644 *pcbStructInfo = bytesNeeded;
3645 else if (*pcbStructInfo < bytesNeeded)
3647 SetLastError(ERROR_MORE_DATA);
3648 *pcbStructInfo = bytesNeeded;
3649 ret = FALSE;
3651 else
3653 CRYPT_DATA_BLOB *blob;
3655 *pcbStructInfo = bytesNeeded;
3656 blob = pvStructInfo;
3657 blob->cbData = dataLen;
3658 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3659 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
3660 else
3662 assert(blob->pbData);
3663 if (blob->cbData)
3664 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
3665 blob->cbData);
3669 return ret;
3672 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
3673 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3674 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3676 BOOL ret;
3678 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3679 pDecodePara, pvStructInfo, *pcbStructInfo);
3681 __TRY
3683 DWORD bytesNeeded;
3685 if (!cbEncoded)
3687 SetLastError(CRYPT_E_ASN1_CORRUPT);
3688 ret = FALSE;
3690 else if (pbEncoded[0] != ASN_OCTETSTRING)
3692 SetLastError(CRYPT_E_ASN1_BADTAG);
3693 ret = FALSE;
3695 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3696 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3698 if (!pvStructInfo)
3699 *pcbStructInfo = bytesNeeded;
3700 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3701 pvStructInfo, pcbStructInfo, bytesNeeded)))
3703 CRYPT_DATA_BLOB *blob;
3705 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3706 pvStructInfo = *(BYTE **)pvStructInfo;
3707 blob = pvStructInfo;
3708 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
3709 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3710 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3711 &bytesNeeded, NULL);
3715 __EXCEPT_PAGE_FAULT
3717 SetLastError(STATUS_ACCESS_VIOLATION);
3718 ret = FALSE;
3720 __ENDTRY
3721 return ret;
3724 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3725 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3727 BOOL ret;
3728 DWORD bytesNeeded, dataLen;
3729 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3731 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3732 pvStructInfo, *pcbStructInfo, pcbDecoded);
3734 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3736 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3737 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3738 else
3739 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3740 if (pcbDecoded)
3741 *pcbDecoded = 1 + lenBytes + dataLen;
3742 if (!pvStructInfo)
3743 *pcbStructInfo = bytesNeeded;
3744 else if (*pcbStructInfo < bytesNeeded)
3746 *pcbStructInfo = bytesNeeded;
3747 SetLastError(ERROR_MORE_DATA);
3748 ret = FALSE;
3750 else
3752 CRYPT_BIT_BLOB *blob;
3754 *pcbStructInfo = bytesNeeded;
3755 blob = pvStructInfo;
3756 blob->cbData = dataLen - 1;
3757 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3758 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3760 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3762 else
3764 assert(blob->pbData);
3765 if (blob->cbData)
3767 BYTE mask = 0xff << blob->cUnusedBits;
3769 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3770 blob->cbData);
3771 blob->pbData[blob->cbData - 1] &= mask;
3776 return ret;
3779 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3780 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3781 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3783 BOOL ret;
3785 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3786 pDecodePara, pvStructInfo, pcbStructInfo);
3788 __TRY
3790 DWORD bytesNeeded;
3792 if (!cbEncoded)
3794 SetLastError(CRYPT_E_ASN1_CORRUPT);
3795 ret = FALSE;
3797 else if (pbEncoded[0] != ASN_BITSTRING)
3799 SetLastError(CRYPT_E_ASN1_BADTAG);
3800 ret = FALSE;
3802 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3803 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3805 if (!pvStructInfo)
3806 *pcbStructInfo = bytesNeeded;
3807 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3808 pvStructInfo, pcbStructInfo, bytesNeeded)))
3810 CRYPT_BIT_BLOB *blob;
3812 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3813 pvStructInfo = *(BYTE **)pvStructInfo;
3814 blob = pvStructInfo;
3815 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3816 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3817 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3818 &bytesNeeded, NULL);
3822 __EXCEPT_PAGE_FAULT
3824 SetLastError(STATUS_ACCESS_VIOLATION);
3825 ret = FALSE;
3827 __ENDTRY
3828 TRACE("returning %d (%08x)\n", ret, GetLastError());
3829 return ret;
3832 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
3833 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3834 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3836 BOOL ret;
3837 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3838 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3839 DWORD size = sizeof(buf);
3841 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3842 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, buf,
3843 &size, pcbDecoded);
3844 if (ret)
3846 if (!pvStructInfo)
3847 *pcbStructInfo = sizeof(int);
3848 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3850 int val, i;
3852 if (blob->pbData[blob->cbData - 1] & 0x80)
3854 /* initialize to a negative value to sign-extend */
3855 val = -1;
3857 else
3858 val = 0;
3859 for (i = 0; i < blob->cbData; i++)
3861 val <<= 8;
3862 val |= blob->pbData[blob->cbData - i - 1];
3864 memcpy(pvStructInfo, &val, sizeof(int));
3867 else if (GetLastError() == ERROR_MORE_DATA)
3868 SetLastError(CRYPT_E_ASN1_LARGE);
3869 return ret;
3872 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3873 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3874 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3876 BOOL ret;
3878 __TRY
3880 DWORD bytesNeeded;
3882 if (!cbEncoded)
3884 SetLastError(CRYPT_E_ASN1_EOD);
3885 ret = FALSE;
3887 else if (pbEncoded[0] != ASN_INTEGER)
3889 SetLastError(CRYPT_E_ASN1_BADTAG);
3890 ret = FALSE;
3892 else
3893 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3894 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3895 if (ret)
3897 if (!pvStructInfo)
3898 *pcbStructInfo = bytesNeeded;
3899 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3900 pvStructInfo, pcbStructInfo, bytesNeeded)))
3902 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3903 pvStructInfo = *(BYTE **)pvStructInfo;
3904 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3905 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3906 &bytesNeeded, NULL);
3910 __EXCEPT_PAGE_FAULT
3912 SetLastError(STATUS_ACCESS_VIOLATION);
3913 ret = FALSE;
3915 __ENDTRY
3916 return ret;
3919 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3920 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3921 DWORD *pcbDecoded)
3923 BOOL ret;
3924 DWORD bytesNeeded, dataLen;
3926 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3928 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3930 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3931 if (pcbDecoded)
3932 *pcbDecoded = 1 + lenBytes + dataLen;
3933 if (!pvStructInfo)
3934 *pcbStructInfo = bytesNeeded;
3935 else if (*pcbStructInfo < bytesNeeded)
3937 *pcbStructInfo = bytesNeeded;
3938 SetLastError(ERROR_MORE_DATA);
3939 ret = FALSE;
3941 else
3943 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
3945 *pcbStructInfo = bytesNeeded;
3946 blob->cbData = dataLen;
3947 assert(blob->pbData);
3948 if (blob->cbData)
3950 DWORD i;
3952 for (i = 0; i < blob->cbData; i++)
3954 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3955 dataLen - i - 1);
3960 return ret;
3963 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3964 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3965 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3967 BOOL ret;
3969 __TRY
3971 DWORD bytesNeeded;
3973 if (pbEncoded[0] != ASN_INTEGER)
3975 SetLastError(CRYPT_E_ASN1_BADTAG);
3976 ret = FALSE;
3978 else
3979 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3980 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3981 if (ret)
3983 if (!pvStructInfo)
3984 *pcbStructInfo = bytesNeeded;
3985 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3986 pvStructInfo, pcbStructInfo, bytesNeeded)))
3988 CRYPT_INTEGER_BLOB *blob;
3990 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3991 pvStructInfo = *(BYTE **)pvStructInfo;
3992 blob = pvStructInfo;
3993 blob->pbData = (BYTE *)pvStructInfo +
3994 sizeof(CRYPT_INTEGER_BLOB);
3995 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3996 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3997 &bytesNeeded, NULL);
4001 __EXCEPT_PAGE_FAULT
4003 SetLastError(STATUS_ACCESS_VIOLATION);
4004 ret = FALSE;
4006 __ENDTRY
4007 return ret;
4010 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
4011 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4012 DWORD *pcbDecoded)
4014 BOOL ret;
4016 if (pbEncoded[0] == ASN_INTEGER)
4018 DWORD bytesNeeded, dataLen;
4020 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4022 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4024 if (pcbDecoded)
4025 *pcbDecoded = 1 + lenBytes + dataLen;
4026 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4027 if (!pvStructInfo)
4028 *pcbStructInfo = bytesNeeded;
4029 else if (*pcbStructInfo < bytesNeeded)
4031 *pcbStructInfo = bytesNeeded;
4032 SetLastError(ERROR_MORE_DATA);
4033 ret = FALSE;
4035 else
4037 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4039 *pcbStructInfo = bytesNeeded;
4040 blob->cbData = dataLen;
4041 assert(blob->pbData);
4042 /* remove leading zero byte if it exists */
4043 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4045 blob->cbData--;
4046 blob->pbData++;
4048 if (blob->cbData)
4050 DWORD i;
4052 for (i = 0; i < blob->cbData; i++)
4054 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4055 dataLen - i - 1);
4061 else
4063 SetLastError(CRYPT_E_ASN1_BADTAG);
4064 ret = FALSE;
4066 return ret;
4069 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4070 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4071 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4073 BOOL ret;
4075 __TRY
4077 DWORD bytesNeeded;
4079 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4080 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4082 if (!pvStructInfo)
4083 *pcbStructInfo = bytesNeeded;
4084 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4085 pvStructInfo, pcbStructInfo, bytesNeeded)))
4087 CRYPT_INTEGER_BLOB *blob;
4089 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4090 pvStructInfo = *(BYTE **)pvStructInfo;
4091 blob = pvStructInfo;
4092 blob->pbData = (BYTE *)pvStructInfo +
4093 sizeof(CRYPT_INTEGER_BLOB);
4094 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4095 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4096 &bytesNeeded, NULL);
4100 __EXCEPT_PAGE_FAULT
4102 SetLastError(STATUS_ACCESS_VIOLATION);
4103 ret = FALSE;
4105 __ENDTRY
4106 return ret;
4109 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4110 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4111 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4113 BOOL ret;
4115 if (!pvStructInfo)
4117 *pcbStructInfo = sizeof(int);
4118 return TRUE;
4120 __TRY
4122 if (pbEncoded[0] == ASN_ENUMERATED)
4124 unsigned int val = 0, i;
4126 if (cbEncoded <= 1)
4128 SetLastError(CRYPT_E_ASN1_EOD);
4129 ret = FALSE;
4131 else if (pbEncoded[1] == 0)
4133 SetLastError(CRYPT_E_ASN1_CORRUPT);
4134 ret = FALSE;
4136 else
4138 /* A little strange looking, but we have to accept a sign byte:
4139 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4140 * assuming a small length is okay here, it has to be in short
4141 * form.
4143 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4145 SetLastError(CRYPT_E_ASN1_LARGE);
4146 return FALSE;
4148 for (i = 0; i < pbEncoded[1]; i++)
4150 val <<= 8;
4151 val |= pbEncoded[2 + i];
4153 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4154 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4156 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4157 pvStructInfo = *(BYTE **)pvStructInfo;
4158 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4162 else
4164 SetLastError(CRYPT_E_ASN1_BADTAG);
4165 ret = FALSE;
4168 __EXCEPT_PAGE_FAULT
4170 SetLastError(STATUS_ACCESS_VIOLATION);
4171 ret = FALSE;
4173 __ENDTRY
4174 return ret;
4177 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4178 * if it fails.
4180 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4181 do { \
4182 BYTE i; \
4184 (word) = 0; \
4185 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4187 if (!isdigit(*(pbEncoded))) \
4189 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4190 ret = FALSE; \
4192 else \
4194 (word) *= 10; \
4195 (word) += *(pbEncoded)++ - '0'; \
4198 } while (0)
4200 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4201 SYSTEMTIME *sysTime)
4203 BOOL ret = TRUE;
4205 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4207 WORD hours, minutes = 0;
4208 BYTE sign = *pbEncoded++;
4210 len--;
4211 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4212 if (ret && hours >= 24)
4214 SetLastError(CRYPT_E_ASN1_CORRUPT);
4215 ret = FALSE;
4217 else if (len >= 2)
4219 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4220 if (ret && minutes >= 60)
4222 SetLastError(CRYPT_E_ASN1_CORRUPT);
4223 ret = FALSE;
4226 if (ret)
4228 if (sign == '+')
4230 sysTime->wHour += hours;
4231 sysTime->wMinute += minutes;
4233 else
4235 if (hours > sysTime->wHour)
4237 sysTime->wDay--;
4238 sysTime->wHour = 24 - (hours - sysTime->wHour);
4240 else
4241 sysTime->wHour -= hours;
4242 if (minutes > sysTime->wMinute)
4244 sysTime->wHour--;
4245 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4247 else
4248 sysTime->wMinute -= minutes;
4252 return ret;
4255 #define MIN_ENCODED_TIME_LENGTH 10
4257 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4258 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4259 DWORD *pcbDecoded)
4261 BOOL ret = FALSE;
4263 if (pbEncoded[0] == ASN_UTCTIME)
4265 if (cbEncoded <= 1)
4266 SetLastError(CRYPT_E_ASN1_EOD);
4267 else if (pbEncoded[1] > 0x7f)
4269 /* long-form date strings really can't be valid */
4270 SetLastError(CRYPT_E_ASN1_CORRUPT);
4272 else
4274 SYSTEMTIME sysTime = { 0 };
4275 BYTE len = pbEncoded[1];
4277 if (len < MIN_ENCODED_TIME_LENGTH)
4278 SetLastError(CRYPT_E_ASN1_CORRUPT);
4279 else
4281 ret = TRUE;
4282 if (pcbDecoded)
4283 *pcbDecoded = 2 + len;
4284 pbEncoded += 2;
4285 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4286 if (sysTime.wYear >= 50)
4287 sysTime.wYear += 1900;
4288 else
4289 sysTime.wYear += 2000;
4290 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4291 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4292 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4293 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4294 if (ret && len > 0)
4296 if (len >= 2 && isdigit(*pbEncoded) &&
4297 isdigit(*(pbEncoded + 1)))
4298 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4299 sysTime.wSecond);
4300 else if (isdigit(*pbEncoded))
4301 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4302 sysTime.wSecond);
4303 if (ret)
4304 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4305 &sysTime);
4307 if (ret)
4309 if (!pvStructInfo)
4310 *pcbStructInfo = sizeof(FILETIME);
4311 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4312 sizeof(FILETIME))))
4313 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4318 else
4319 SetLastError(CRYPT_E_ASN1_BADTAG);
4320 return ret;
4323 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4324 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4325 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4327 BOOL ret = FALSE;
4329 __TRY
4331 DWORD bytesNeeded;
4333 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4334 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4335 if (ret)
4337 if (!pvStructInfo)
4338 *pcbStructInfo = bytesNeeded;
4339 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4340 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4342 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4343 pvStructInfo = *(BYTE **)pvStructInfo;
4344 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4345 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4346 &bytesNeeded, NULL);
4350 __EXCEPT_PAGE_FAULT
4352 SetLastError(STATUS_ACCESS_VIOLATION);
4354 __ENDTRY
4355 return ret;
4358 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
4359 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4360 DWORD *pcbDecoded)
4362 BOOL ret = FALSE;
4364 if (pbEncoded[0] == ASN_GENERALTIME)
4366 if (cbEncoded <= 1)
4367 SetLastError(CRYPT_E_ASN1_EOD);
4368 else if (pbEncoded[1] > 0x7f)
4370 /* long-form date strings really can't be valid */
4371 SetLastError(CRYPT_E_ASN1_CORRUPT);
4373 else
4375 BYTE len = pbEncoded[1];
4377 if (len < MIN_ENCODED_TIME_LENGTH)
4378 SetLastError(CRYPT_E_ASN1_CORRUPT);
4379 else
4381 SYSTEMTIME sysTime = { 0 };
4383 ret = TRUE;
4384 if (pcbDecoded)
4385 *pcbDecoded = 2 + len;
4386 pbEncoded += 2;
4387 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
4388 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4389 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4390 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4391 if (ret && len > 0)
4393 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4394 sysTime.wMinute);
4395 if (ret && len > 0)
4396 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4397 sysTime.wSecond);
4398 if (ret && len > 0 && (*pbEncoded == '.' ||
4399 *pbEncoded == ','))
4401 BYTE digits;
4403 pbEncoded++;
4404 len--;
4405 /* workaround macro weirdness */
4406 digits = min(len, 3);
4407 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
4408 sysTime.wMilliseconds);
4410 if (ret)
4411 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4412 &sysTime);
4414 if (ret)
4416 if (!pvStructInfo)
4417 *pcbStructInfo = sizeof(FILETIME);
4418 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4419 sizeof(FILETIME))))
4420 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4425 else
4426 SetLastError(CRYPT_E_ASN1_BADTAG);
4427 return ret;
4430 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4431 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4432 DWORD *pcbDecoded)
4434 BOOL ret;
4435 InternalDecodeFunc decode = NULL;
4437 if (pbEncoded[0] == ASN_UTCTIME)
4438 decode = CRYPT_AsnDecodeUtcTimeInternal;
4439 else if (pbEncoded[0] == ASN_GENERALTIME)
4440 decode = CRYPT_AsnDecodeGeneralizedTime;
4441 if (decode)
4442 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
4443 pcbStructInfo, pcbDecoded);
4444 else
4446 SetLastError(CRYPT_E_ASN1_BADTAG);
4447 ret = FALSE;
4449 return ret;
4452 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
4453 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4454 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4456 BOOL ret;
4458 __TRY
4460 DWORD bytesNeeded;
4462 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4463 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4464 if (ret)
4466 if (!pvStructInfo)
4467 *pcbStructInfo = bytesNeeded;
4468 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4469 pvStructInfo, pcbStructInfo, bytesNeeded)))
4471 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4472 pvStructInfo = *(BYTE **)pvStructInfo;
4473 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4474 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4475 &bytesNeeded, NULL);
4479 __EXCEPT_PAGE_FAULT
4481 SetLastError(STATUS_ACCESS_VIOLATION);
4482 ret = FALSE;
4484 __ENDTRY
4485 return ret;
4488 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
4489 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4490 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4492 BOOL ret = TRUE;
4494 __TRY
4496 if (pbEncoded[0] == ASN_SEQUENCEOF)
4498 DWORD bytesNeeded, dataLen, remainingLen, cValue;
4500 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4502 BYTE lenBytes;
4503 const BYTE *ptr;
4505 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4506 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
4507 cValue = 0;
4508 ptr = pbEncoded + 1 + lenBytes;
4509 remainingLen = dataLen;
4510 while (ret && remainingLen)
4512 DWORD nextLen;
4514 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4515 if (ret)
4517 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4519 remainingLen -= 1 + nextLenBytes + nextLen;
4520 ptr += 1 + nextLenBytes + nextLen;
4521 bytesNeeded += sizeof(CRYPT_DER_BLOB);
4522 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
4523 bytesNeeded += 1 + nextLenBytes + nextLen;
4524 cValue++;
4527 if (ret)
4529 CRYPT_SEQUENCE_OF_ANY *seq;
4530 BYTE *nextPtr;
4531 DWORD i;
4533 if (!pvStructInfo)
4534 *pcbStructInfo = bytesNeeded;
4535 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4536 pvStructInfo, pcbStructInfo, bytesNeeded)))
4538 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4539 pvStructInfo = *(BYTE **)pvStructInfo;
4540 seq = pvStructInfo;
4541 seq->cValue = cValue;
4542 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
4543 sizeof(*seq));
4544 nextPtr = (BYTE *)seq->rgValue +
4545 cValue * sizeof(CRYPT_DER_BLOB);
4546 ptr = pbEncoded + 1 + lenBytes;
4547 remainingLen = dataLen;
4548 i = 0;
4549 while (ret && remainingLen)
4551 DWORD nextLen;
4553 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4554 if (ret)
4556 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4558 seq->rgValue[i].cbData = 1 + nextLenBytes +
4559 nextLen;
4560 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4561 seq->rgValue[i].pbData = (BYTE *)ptr;
4562 else
4564 seq->rgValue[i].pbData = nextPtr;
4565 memcpy(nextPtr, ptr, 1 + nextLenBytes +
4566 nextLen);
4567 nextPtr += 1 + nextLenBytes + nextLen;
4569 remainingLen -= 1 + nextLenBytes + nextLen;
4570 ptr += 1 + nextLenBytes + nextLen;
4571 i++;
4578 else
4580 SetLastError(CRYPT_E_ASN1_BADTAG);
4581 ret = FALSE;
4584 __EXCEPT_PAGE_FAULT
4586 SetLastError(STATUS_ACCESS_VIOLATION);
4587 ret = FALSE;
4589 __ENDTRY
4590 return ret;
4593 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4594 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4595 DWORD *pcbDecoded)
4597 BOOL ret;
4599 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
4601 DWORD bytesNeeded, dataLen;
4603 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4605 struct AsnArrayDescriptor arrayDesc = {
4606 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
4607 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
4608 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
4609 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4610 DWORD nameLen;
4612 if (dataLen)
4614 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4615 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4616 0, NULL, NULL, &nameLen, NULL, NULL);
4617 /* The CERT_ALT_NAME_INFO's size is included by CRYPT_AsnDecodeArray
4618 * as the sizeof(struct GenericArray), so don't include it in the
4619 * total bytes needed.
4621 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
4622 sizeof(CERT_ALT_NAME_INFO);
4624 else
4625 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
4626 if (pcbDecoded)
4627 *pcbDecoded = 1 + lenBytes + dataLen;
4628 if (!pvStructInfo)
4629 *pcbStructInfo = bytesNeeded;
4630 else if (*pcbStructInfo < bytesNeeded)
4632 *pcbStructInfo = bytesNeeded;
4633 SetLastError(ERROR_MORE_DATA);
4634 ret = FALSE;
4636 else
4638 CRL_DIST_POINT_NAME *name = pvStructInfo;
4640 *pcbStructInfo = bytesNeeded;
4641 if (dataLen)
4643 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
4644 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4645 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4646 0, NULL, &name->u.FullName, &nameLen, NULL,
4647 name->u.FullName.rgAltEntry);
4649 else
4650 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
4654 else
4656 SetLastError(CRYPT_E_ASN1_BADTAG);
4657 ret = FALSE;
4659 return ret;
4662 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
4663 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4665 struct AsnDecodeSequenceItem items[] = {
4666 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
4667 DistPointName), CRYPT_AsnDecodeDistPointName,
4668 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
4669 DistPointName.u.FullName.rgAltEntry), 0 },
4670 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
4671 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
4672 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
4673 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
4674 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
4675 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
4677 CRL_DIST_POINT *point = pvStructInfo;
4678 BOOL ret;
4680 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4681 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4682 pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
4683 return ret;
4686 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
4687 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4688 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4690 BOOL ret;
4692 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4693 pDecodePara, pvStructInfo, *pcbStructInfo);
4695 __TRY
4697 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4698 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
4699 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
4701 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4702 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4704 __EXCEPT_PAGE_FAULT
4706 SetLastError(STATUS_ACCESS_VIOLATION);
4707 ret = FALSE;
4709 __ENDTRY
4710 return ret;
4713 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
4714 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4715 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4717 BOOL ret;
4719 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4720 pDecodePara, pvStructInfo, *pcbStructInfo);
4722 __TRY
4724 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4725 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4727 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4728 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4730 __EXCEPT_PAGE_FAULT
4732 SetLastError(STATUS_ACCESS_VIOLATION);
4733 ret = FALSE;
4735 __ENDTRY
4736 return ret;
4739 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4740 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4741 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4743 BOOL ret;
4745 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4746 pDecodePara, pvStructInfo, *pcbStructInfo);
4748 __TRY
4750 struct AsnDecodeSequenceItem items[] = {
4751 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4752 DistPointName), CRYPT_AsnDecodeDistPointName,
4753 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4754 offsetof(CRL_ISSUING_DIST_POINT,
4755 DistPointName.u.FullName.rgAltEntry), 0 },
4756 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4757 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4758 FALSE, 0 },
4759 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4760 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4761 FALSE, 0 },
4762 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4763 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4764 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4765 OnlySomeReasonFlags.pbData), 0 },
4766 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4767 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4770 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4771 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4772 pcbStructInfo, NULL, NULL);
4774 __EXCEPT_PAGE_FAULT
4776 SetLastError(STATUS_ACCESS_VIOLATION);
4777 ret = FALSE;
4779 __ENDTRY
4780 return ret;
4783 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
4784 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4785 DWORD *pcbDecoded)
4787 BOOL ret = FALSE;
4789 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4790 pvStructInfo, *pcbStructInfo, pcbDecoded);
4792 if (!cbEncoded)
4794 SetLastError(CRYPT_E_ASN1_EOD);
4795 return FALSE;
4797 if (pbEncoded[0] != (ASN_CONTEXT | 1))
4799 SetLastError(CRYPT_E_ASN1_BADTAG);
4800 return FALSE;
4802 /* The BOOL is implicit: if the integer is present, then it's TRUE */
4803 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
4804 pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo,
4805 pcbDecoded);
4806 if (ret && pvStructInfo)
4807 *(BOOL *)pvStructInfo = TRUE;
4808 TRACE("returning %d\n", ret);
4809 return ret;
4812 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
4813 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4814 DWORD *pcbDecoded)
4816 BOOL ret;
4817 struct AsnDecodeSequenceItem items[] = {
4818 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
4819 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
4820 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
4821 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
4822 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
4823 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
4824 CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0,
4825 0 },
4827 CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
4829 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4830 pvStructInfo, *pcbStructInfo, pcbDecoded);
4832 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4833 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4834 pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
4835 if (pcbDecoded)
4837 TRACE("%d\n", *pcbDecoded);
4838 if (*pcbDecoded < cbEncoded)
4839 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
4840 *(pbEncoded + *pcbDecoded + 1));
4842 TRACE("returning %d\n", ret);
4843 return ret;
4846 static BOOL CRYPT_AsnDecodeSubtreeArray(const BYTE *pbEncoded,
4847 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4848 DWORD *pcbDecoded)
4850 BOOL ret = TRUE;
4851 struct AsnArrayDescriptor arrayDesc = { 0,
4852 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4853 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4854 struct GenericArray *array = pvStructInfo;
4856 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4857 pvStructInfo, *pcbStructInfo, pcbDecoded);
4859 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4860 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4861 array ? array->rgItems : NULL);
4862 return ret;
4866 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
4867 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4868 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4870 BOOL ret = FALSE;
4872 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4873 pDecodePara, pvStructInfo, *pcbStructInfo);
4875 __TRY
4877 struct AsnDecodeSequenceItem items[] = {
4878 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4879 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
4880 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4881 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
4882 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
4883 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4884 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4885 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
4888 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4889 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4890 pcbStructInfo, NULL, NULL);
4892 __EXCEPT_PAGE_FAULT
4894 SetLastError(STATUS_ACCESS_VIOLATION);
4896 __ENDTRY
4897 return ret;
4900 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
4901 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4902 DWORD *pcbDecoded)
4904 BOOL ret;
4905 struct AsnDecodeSequenceItem items[] = {
4906 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4907 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4908 Issuer.pbData) },
4909 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4910 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4911 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4913 CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
4915 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4916 pvStructInfo, *pcbStructInfo, pcbDecoded);
4918 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4919 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4920 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4921 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4923 SetLastError(CRYPT_E_ASN1_CORRUPT);
4924 ret = FALSE;
4926 TRACE("returning %d\n", ret);
4927 return ret;
4930 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4931 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4932 DWORD *pcbDecoded)
4934 CMSG_SIGNER_INFO *info = pvStructInfo;
4935 struct AsnDecodeSequenceItem items[] = {
4936 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4937 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4938 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4939 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4940 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4941 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4942 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4943 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4944 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4945 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4946 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4947 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4948 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4949 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4950 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4951 HashEncryptionAlgorithm.pszObjId), 0 },
4952 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4953 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4954 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4955 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4956 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4957 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4958 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4960 BOOL ret;
4962 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4963 pvStructInfo, *pcbStructInfo);
4965 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4966 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4967 pcbDecoded, info ? info->Issuer.pbData : NULL);
4968 return ret;
4971 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4972 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4973 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4975 BOOL ret = FALSE;
4977 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4978 pDecodePara, pvStructInfo, *pcbStructInfo);
4980 __TRY
4982 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4983 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4984 if (ret && pvStructInfo)
4986 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4987 pcbStructInfo, *pcbStructInfo);
4988 if (ret)
4990 CMSG_SIGNER_INFO *info;
4992 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4993 pvStructInfo = *(BYTE **)pvStructInfo;
4994 info = pvStructInfo;
4995 info->Issuer.pbData = ((BYTE *)info +
4996 sizeof(CMSG_SIGNER_INFO));
4997 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4998 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4999 pcbStructInfo, NULL);
5003 __EXCEPT_PAGE_FAULT
5005 SetLastError(STATUS_ACCESS_VIOLATION);
5007 __ENDTRY
5008 TRACE("returning %d\n", ret);
5009 return ret;
5012 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
5013 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5014 DWORD *pcbDecoded)
5016 CERT_ID *id = pvStructInfo;
5017 BOOL ret = FALSE;
5019 if (*pbEncoded == ASN_SEQUENCEOF)
5021 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
5022 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
5023 if (ret)
5025 if (id)
5026 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5027 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
5028 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5029 sizeof(CERT_ISSUER_SERIAL_NUMBER);
5030 else
5031 *pcbStructInfo = sizeof(CERT_ID);
5034 else if (*pbEncoded == (ASN_CONTEXT | 0))
5036 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
5037 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
5038 if (ret)
5040 if (id)
5041 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
5042 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
5043 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5044 sizeof(CRYPT_DATA_BLOB);
5045 else
5046 *pcbStructInfo = sizeof(CERT_ID);
5049 else
5050 SetLastError(CRYPT_E_ASN1_BADTAG);
5051 return ret;
5054 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5055 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5056 DWORD *pcbDecoded)
5058 CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
5059 struct AsnDecodeSequenceItem items[] = {
5060 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5061 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5062 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5063 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5064 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
5065 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5066 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5067 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5068 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5069 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5070 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5071 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5072 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5073 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5074 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5075 HashEncryptionAlgorithm.pszObjId), 0 },
5076 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5077 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5078 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5079 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5080 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5081 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5082 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5084 BOOL ret;
5086 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5087 pvStructInfo, *pcbStructInfo);
5089 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5090 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5091 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
5092 return ret;
5095 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5096 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5097 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5099 BOOL ret = FALSE;
5101 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5102 pDecodePara, pvStructInfo, *pcbStructInfo);
5104 __TRY
5106 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5107 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5108 if (ret && pvStructInfo)
5110 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5111 pcbStructInfo, *pcbStructInfo);
5112 if (ret)
5114 CMSG_CMS_SIGNER_INFO *info;
5116 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5117 pvStructInfo = *(BYTE **)pvStructInfo;
5118 info = pvStructInfo;
5119 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
5120 sizeof(CMSG_CMS_SIGNER_INFO));
5121 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5122 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5123 pcbStructInfo, NULL);
5127 __EXCEPT_PAGE_FAULT
5129 SetLastError(STATUS_ACCESS_VIOLATION);
5131 __ENDTRY
5132 TRACE("returning %d\n", ret);
5133 return ret;
5136 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5137 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5139 BOOL ret;
5140 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5141 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5142 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
5143 struct GenericArray *array = pvStructInfo;
5145 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5146 pvStructInfo, *pcbStructInfo, pcbDecoded);
5148 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
5149 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
5150 array ? array->rgItems : NULL);
5151 return ret;
5154 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5155 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5156 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5158 BOOL ret = FALSE;
5159 struct AsnDecodeSequenceItem items[] = {
5160 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5161 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5162 /* Placeholder for the hash algorithms - redundant with those in the
5163 * signers, so just ignore them.
5165 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5166 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5167 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5168 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5169 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5170 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
5171 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
5172 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5173 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5174 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
5175 sizeof(struct GenericArray), TRUE, TRUE,
5176 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5177 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5178 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
5179 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5182 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5183 pDecodePara, signedInfo, *pcbSignedInfo);
5185 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5186 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5187 NULL, NULL);
5188 TRACE("returning %d\n", ret);
5189 return ret;
5192 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
5193 LPCSTR lpszStructType)
5195 CryptDecodeObjectExFunc decodeFunc = NULL;
5197 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
5198 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
5200 SetLastError(ERROR_FILE_NOT_FOUND);
5201 return NULL;
5203 if (!HIWORD(lpszStructType))
5205 switch (LOWORD(lpszStructType))
5207 case LOWORD(X509_CERT):
5208 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
5209 break;
5210 case LOWORD(X509_CERT_TO_BE_SIGNED):
5211 decodeFunc = CRYPT_AsnDecodeCert;
5212 break;
5213 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
5214 decodeFunc = CRYPT_AsnDecodeCRL;
5215 break;
5216 case LOWORD(X509_EXTENSIONS):
5217 decodeFunc = CRYPT_AsnDecodeExtensions;
5218 break;
5219 case LOWORD(X509_NAME_VALUE):
5220 decodeFunc = CRYPT_AsnDecodeNameValue;
5221 break;
5222 case LOWORD(X509_NAME):
5223 decodeFunc = CRYPT_AsnDecodeName;
5224 break;
5225 case LOWORD(X509_PUBLIC_KEY_INFO):
5226 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
5227 break;
5228 case LOWORD(X509_AUTHORITY_KEY_ID):
5229 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5230 break;
5231 case LOWORD(X509_ALTERNATE_NAME):
5232 decodeFunc = CRYPT_AsnDecodeAltName;
5233 break;
5234 case LOWORD(X509_BASIC_CONSTRAINTS):
5235 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5236 break;
5237 case LOWORD(X509_BASIC_CONSTRAINTS2):
5238 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5239 break;
5240 case LOWORD(X509_CERT_POLICIES):
5241 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5242 break;
5243 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
5244 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
5245 break;
5246 case LOWORD(X509_UNICODE_NAME):
5247 decodeFunc = CRYPT_AsnDecodeUnicodeName;
5248 break;
5249 case LOWORD(PKCS_ATTRIBUTE):
5250 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
5251 break;
5252 case LOWORD(X509_UNICODE_NAME_VALUE):
5253 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
5254 break;
5255 case LOWORD(X509_OCTET_STRING):
5256 decodeFunc = CRYPT_AsnDecodeOctets;
5257 break;
5258 case LOWORD(X509_BITS):
5259 case LOWORD(X509_KEY_USAGE):
5260 decodeFunc = CRYPT_AsnDecodeBits;
5261 break;
5262 case LOWORD(X509_INTEGER):
5263 decodeFunc = CRYPT_AsnDecodeInt;
5264 break;
5265 case LOWORD(X509_MULTI_BYTE_INTEGER):
5266 decodeFunc = CRYPT_AsnDecodeInteger;
5267 break;
5268 case LOWORD(X509_MULTI_BYTE_UINT):
5269 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
5270 break;
5271 case LOWORD(X509_ENUMERATED):
5272 decodeFunc = CRYPT_AsnDecodeEnumerated;
5273 break;
5274 case LOWORD(X509_CHOICE_OF_TIME):
5275 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
5276 break;
5277 case LOWORD(X509_AUTHORITY_KEY_ID2):
5278 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5279 break;
5280 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
5281 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5282 break;
5283 case LOWORD(PKCS_CONTENT_INFO):
5284 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
5285 break;
5286 case LOWORD(X509_SEQUENCE_OF_ANY):
5287 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
5288 break;
5289 case LOWORD(PKCS_UTC_TIME):
5290 decodeFunc = CRYPT_AsnDecodeUtcTime;
5291 break;
5292 case LOWORD(X509_CRL_DIST_POINTS):
5293 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5294 break;
5295 case LOWORD(X509_ENHANCED_KEY_USAGE):
5296 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5297 break;
5298 case LOWORD(PKCS_CTL):
5299 decodeFunc = CRYPT_AsnDecodeCTL;
5300 break;
5301 case LOWORD(PKCS_SMIME_CAPABILITIES):
5302 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5303 break;
5304 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
5305 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5306 break;
5307 case LOWORD(PKCS_ATTRIBUTES):
5308 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
5309 break;
5310 case LOWORD(X509_ISSUING_DIST_POINT):
5311 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5312 break;
5313 case LOWORD(X509_NAME_CONSTRAINTS):
5314 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5315 break;
5316 case LOWORD(PKCS7_SIGNER_INFO):
5317 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
5318 break;
5319 case LOWORD(CMS_SIGNER_INFO):
5320 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
5321 break;
5324 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
5325 decodeFunc = CRYPT_AsnDecodeExtensions;
5326 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
5327 decodeFunc = CRYPT_AsnDecodeUtcTime;
5328 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
5329 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5330 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
5331 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5332 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
5333 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5334 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
5335 decodeFunc = CRYPT_AsnDecodeEnumerated;
5336 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
5337 decodeFunc = CRYPT_AsnDecodeBits;
5338 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
5339 decodeFunc = CRYPT_AsnDecodeOctets;
5340 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
5341 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5342 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
5343 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5344 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
5345 decodeFunc = CRYPT_AsnDecodeAltName;
5346 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
5347 decodeFunc = CRYPT_AsnDecodeAltName;
5348 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
5349 decodeFunc = CRYPT_AsnDecodeAltName;
5350 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
5351 decodeFunc = CRYPT_AsnDecodeAltName;
5352 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
5353 decodeFunc = CRYPT_AsnDecodeAltName;
5354 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
5355 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5356 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
5357 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5358 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
5359 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5360 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
5361 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5362 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
5363 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5364 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
5365 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5366 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
5367 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5368 else if (!strcmp(lpszStructType, szOID_CTL))
5369 decodeFunc = CRYPT_AsnDecodeCTL;
5370 return decodeFunc;
5373 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
5374 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5376 static HCRYPTOIDFUNCSET set = NULL;
5377 CryptDecodeObjectFunc decodeFunc = NULL;
5379 if (!set)
5380 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
5381 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5382 (void **)&decodeFunc, hFunc);
5383 return decodeFunc;
5386 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
5387 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5389 static HCRYPTOIDFUNCSET set = NULL;
5390 CryptDecodeObjectExFunc decodeFunc = NULL;
5392 if (!set)
5393 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
5394 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5395 (void **)&decodeFunc, hFunc);
5396 return decodeFunc;
5399 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5400 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
5401 DWORD *pcbStructInfo)
5403 BOOL ret = FALSE;
5404 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
5405 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
5406 HCRYPTOIDFUNCADDR hFunc = NULL;
5408 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
5409 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
5410 pvStructInfo, pcbStructInfo);
5412 if (!pvStructInfo && !pcbStructInfo)
5414 SetLastError(ERROR_INVALID_PARAMETER);
5415 return FALSE;
5417 if (cbEncoded > MAX_ENCODED_LEN)
5419 SetLastError(CRYPT_E_ASN1_LARGE);
5420 return FALSE;
5423 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
5424 lpszStructType)))
5426 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5427 debugstr_a(lpszStructType));
5428 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
5429 lpszStructType, &hFunc);
5430 if (!pCryptDecodeObject)
5431 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
5432 lpszStructType, &hFunc);
5434 if (pCryptDecodeObject)
5435 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5436 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5437 else if (pCryptDecodeObjectEx)
5438 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
5439 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
5440 pvStructInfo, pcbStructInfo);
5441 if (hFunc)
5442 CryptFreeOIDFunctionAddress(hFunc, 0);
5443 TRACE_(crypt)("returning %d\n", ret);
5444 return ret;
5447 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5448 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5449 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5451 BOOL ret = FALSE;
5452 CryptDecodeObjectExFunc decodeFunc;
5453 HCRYPTOIDFUNCADDR hFunc = NULL;
5455 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
5456 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5457 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5459 if (!pvStructInfo && !pcbStructInfo)
5461 SetLastError(ERROR_INVALID_PARAMETER);
5462 return FALSE;
5464 if (cbEncoded > MAX_ENCODED_LEN)
5466 SetLastError(CRYPT_E_ASN1_LARGE);
5467 return FALSE;
5470 SetLastError(NOERROR);
5471 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5472 *(BYTE **)pvStructInfo = NULL;
5473 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
5474 if (!decodeFunc)
5476 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5477 debugstr_a(lpszStructType));
5478 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
5479 &hFunc);
5481 if (decodeFunc)
5482 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5483 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5484 else
5486 CryptDecodeObjectFunc pCryptDecodeObject =
5487 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
5489 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
5490 * directly, as that could cause an infinite loop.
5492 if (pCryptDecodeObject)
5494 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5496 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5497 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
5498 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5499 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
5500 ret = pCryptDecodeObject(dwCertEncodingType,
5501 lpszStructType, pbEncoded, cbEncoded, dwFlags,
5502 *(BYTE **)pvStructInfo, pcbStructInfo);
5504 else
5505 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5506 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5509 if (hFunc)
5510 CryptFreeOIDFunctionAddress(hFunc, 0);
5511 TRACE_(crypt)("returning %d\n", ret);
5512 return ret;
5515 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
5517 BOOL ret;
5519 TRACE_(crypt)("(%p)\n", pPFX);
5521 /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
5522 * version integer of length 1 (3 encoded byes) and at least one other
5523 * datum (two encoded bytes), plus at least two bytes for the outer
5524 * sequence. Thus, even an empty PFX blob is at least 7 bytes in length.
5526 if (pPFX->cbData < 7)
5527 ret = FALSE;
5528 else if (pPFX->pbData[0] == ASN_SEQUENCE)
5530 DWORD len;
5532 if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
5534 BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
5536 /* Need at least three bytes for the integer version */
5537 if (pPFX->cbData < 1 + lenLen + 3)
5538 ret = FALSE;
5539 else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
5540 pPFX->pbData[1 + lenLen + 1] != 1 || /* Definite length */
5541 pPFX->pbData[1 + lenLen + 2] != 3) /* PFX version */
5542 ret = FALSE;
5545 else
5546 ret = FALSE;
5547 return ret;
5550 HCERTSTORE WINAPI PFXImportCertStore(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword,
5551 DWORD dwFlags)
5553 FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags);
5554 return NULL;