crypt32: Fix the aligning up to a DWORD_PTR boundary.
[wine/multimedia.git] / dlls / crypt32 / decode.c
blob6cb504777c15e17258ce10a0f75210859f6a57f1
1 /*
2 * Copyright 2005-2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
33 #include "config.h"
34 #include "wine/port.h"
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
41 #define NONAMELESSUNION
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "winnls.h"
47 #include "snmp.h"
48 #include "wine/debug.h"
49 #include "wine/exception.h"
50 #include "crypt32_private.h"
52 /* This is a bit arbitrary, but to set some limit: */
53 #define MAX_ENCODED_LEN 0x02000000
55 #define ASN_FLAGS_MASK 0xe0
56 #define ASN_TYPE_MASK 0x1f
58 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
59 WINE_DECLARE_DEBUG_CHANNEL(crypt);
61 struct GenericArray
63 DWORD cItems;
64 BYTE *rgItems;
67 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
68 DWORD, DWORD, void *, DWORD *);
69 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
70 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
72 /* Internal decoders don't do memory allocation or exception handling, and
73 * they report how many bytes they decoded.
75 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
76 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
78 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
79 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
80 DWORD *pcbDecoded);
81 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
82 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
83 DWORD *pcbDecoded);
84 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
85 * time, doesn't do memory allocation, and doesn't do exception handling.
87 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
88 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
89 DWORD *pcbDecoded);
90 /* Assumes algo->Parameters.pbData is set ahead of time. */
91 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
92 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
93 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
94 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
97 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
98 DWORD *pcbDecoded);
99 /* Doesn't check the tag, assumes the caller does so */
100 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
101 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
102 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
103 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
104 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
105 * member has been initialized, doesn't do exception handling, and doesn't do
106 * memory allocation. Also doesn't check tag, assumes the caller has checked
107 * it.
109 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
110 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
111 DWORD *pcbDecoded);
112 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
113 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
114 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
115 DWORD *pcbDecoded);
116 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
117 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
118 DWORD *pcbDecoded);
120 /* Gets the number of length bytes from the given (leading) length byte */
121 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
123 /* Helper function to get the encoded length of the data starting at pbEncoded,
124 * where pbEncoded[0] is the tag. If the data are too short to contain a
125 * length or if the length is too large for cbEncoded, sets an appropriate
126 * error code and returns FALSE. If the encoded length is unknown due to
127 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
129 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
130 DWORD *len)
132 BOOL ret;
134 if (cbEncoded <= 1)
136 SetLastError(CRYPT_E_ASN1_CORRUPT);
137 ret = FALSE;
139 else if (pbEncoded[1] <= 0x7f)
141 if (pbEncoded[1] + 1 > cbEncoded)
143 SetLastError(CRYPT_E_ASN1_EOD);
144 ret = FALSE;
146 else
148 *len = pbEncoded[1];
149 ret = TRUE;
152 else if (pbEncoded[1] == 0x80)
154 *len = CMSG_INDEFINITE_LENGTH;
155 ret = TRUE;
157 else
159 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
161 if (lenLen > sizeof(DWORD) + 1)
163 SetLastError(CRYPT_E_ASN1_LARGE);
164 ret = FALSE;
166 else if (lenLen + 2 > cbEncoded)
168 SetLastError(CRYPT_E_ASN1_CORRUPT);
169 ret = FALSE;
171 else
173 DWORD out = 0;
175 pbEncoded += 2;
176 while (--lenLen)
178 out <<= 8;
179 out |= *pbEncoded++;
181 if (out + lenLen + 1 > cbEncoded)
183 SetLastError(CRYPT_E_ASN1_EOD);
184 ret = FALSE;
186 else
188 *len = out;
189 ret = TRUE;
193 return ret;
196 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
197 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
199 BOOL ret;
201 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
202 *len == CMSG_INDEFINITE_LENGTH)
204 SetLastError(CRYPT_E_ASN1_CORRUPT);
205 ret = FALSE;
207 return ret;
210 /* Helper function to check *pcbStructInfo, set it to the required size, and
211 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
212 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
213 * pointer to the newly allocated memory.
215 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
216 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
217 DWORD bytesNeeded)
219 BOOL ret = TRUE;
221 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
223 if (pDecodePara && pDecodePara->pfnAlloc)
224 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
225 else
226 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
227 if (!*(BYTE **)pvStructInfo)
228 ret = FALSE;
229 else
230 *pcbStructInfo = bytesNeeded;
232 else if (*pcbStructInfo < bytesNeeded)
234 *pcbStructInfo = bytesNeeded;
235 SetLastError(ERROR_MORE_DATA);
236 ret = FALSE;
238 else
239 *pcbStructInfo = bytesNeeded;
240 return ret;
243 static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
245 if (pDecodePara && pDecodePara->pfnFree)
246 pDecodePara->pfnFree(pv);
247 else
248 LocalFree(pv);
251 /* Helper function to check *pcbStructInfo and set it to the required size.
252 * Assumes pvStructInfo is not NULL.
254 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
256 BOOL ret;
258 if (*pcbStructInfo < bytesNeeded)
260 *pcbStructInfo = bytesNeeded;
261 SetLastError(ERROR_MORE_DATA);
262 ret = FALSE;
264 else
266 *pcbStructInfo = bytesNeeded;
267 ret = TRUE;
269 return ret;
272 /* tag:
273 * The expected tag of the item. If tag is 0, decodeFunc is called
274 * regardless of the tag value seen.
275 * offset:
276 * A sequence is decoded into a struct. The offset member is the
277 * offset of this item within that struct.
278 * decodeFunc:
279 * The decoder function to use. If this is NULL, then the member isn't
280 * decoded, but minSize space is reserved for it.
281 * minSize:
282 * The minimum amount of space occupied after decoding. You must set this.
283 * optional:
284 * If true, and the tag doesn't match the expected tag for this item,
285 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
286 * filled with 0 for this member.
287 * hasPointer, pointerOffset:
288 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
289 * the offset within the struct of the data pointer (or to the
290 * first data pointer, if more than one exist).
291 * size:
292 * Used by CRYPT_AsnDecodeSequence, not for your use.
294 struct AsnDecodeSequenceItem
296 BYTE tag;
297 DWORD offset;
298 InternalDecodeFunc decodeFunc;
299 DWORD minSize;
300 BOOL optional;
301 BOOL hasPointer;
302 DWORD pointerOffset;
303 DWORD size;
306 /* Decodes the items in a sequence, where the items are described in items,
307 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
308 * pvStructInfo. nextData is a pointer to the memory location at which the
309 * first decoded item with a dynamic pointer should point.
310 * Upon decoding, *cbDecoded is the total number of bytes decoded.
311 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
313 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
314 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
315 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
317 BOOL ret;
318 DWORD i, decoded = 0;
319 const BYTE *ptr = pbEncoded;
321 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
322 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
324 for (i = 0, ret = TRUE; ret && i < cItem; i++)
326 if (cbEncoded - (ptr - pbEncoded) != 0)
328 DWORD itemLen;
330 if ((ret = CRYPT_GetLengthIndefinite(ptr,
331 cbEncoded - (ptr - pbEncoded), &itemLen)))
333 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
335 if (ptr[0] == items[i].tag || !items[i].tag)
337 DWORD itemEncodedLen;
339 if (itemLen == CMSG_INDEFINITE_LENGTH)
340 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
341 else
342 itemEncodedLen = 1 + itemLenBytes + itemLen;
343 if (nextData && pvStructInfo && items[i].hasPointer)
345 TRACE("Setting next pointer to %p\n",
346 nextData);
347 *(BYTE **)((BYTE *)pvStructInfo +
348 items[i].pointerOffset) = nextData;
350 if (items[i].decodeFunc)
352 DWORD itemDecoded;
354 if (pvStructInfo)
355 TRACE("decoding item %d\n", i);
356 else
357 TRACE("sizing item %d\n", i);
358 ret = items[i].decodeFunc(ptr, itemEncodedLen,
359 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
360 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
361 : NULL, &items[i].size, &itemDecoded);
362 if (ret)
364 /* Account for alignment padding */
365 items[i].size = ALIGN_DWORD_PTR(items[i].size);
366 TRACE("item %d size: %d\n", i, items[i].size);
367 if (nextData && items[i].hasPointer &&
368 items[i].size > items[i].minSize)
369 nextData += items[i].size - items[i].minSize;
370 if (itemDecoded > itemEncodedLen)
372 WARN("decoded length %d exceeds encoded %d\n",
373 itemDecoded, itemEncodedLen);
374 SetLastError(CRYPT_E_ASN1_CORRUPT);
375 ret = FALSE;
377 else
379 if (itemLen == CMSG_INDEFINITE_LENGTH)
381 if (itemDecoded > itemEncodedLen - 2 ||
382 *(ptr + itemDecoded) != 0 ||
383 *(ptr + itemDecoded + 1) != 0)
385 TRACE("expected 0 TLV\n");
386 SetLastError(CRYPT_E_ASN1_CORRUPT);
387 ret = FALSE;
389 else
390 itemDecoded += 2;
392 if (ret)
394 ptr += itemDecoded;
395 decoded += itemDecoded;
396 TRACE("item %d: decoded %d bytes\n", i,
397 itemDecoded);
401 else if (items[i].optional &&
402 GetLastError() == CRYPT_E_ASN1_BADTAG)
404 TRACE("skipping optional item %d\n", i);
405 items[i].size = items[i].minSize;
406 SetLastError(NOERROR);
407 ret = TRUE;
409 else
410 TRACE("item %d failed: %08x\n", i,
411 GetLastError());
413 else if (itemLen == CMSG_INDEFINITE_LENGTH)
415 ERR("can't use indefinite length encoding without a decoder\n");
416 SetLastError(CRYPT_E_ASN1_CORRUPT);
417 ret = FALSE;
419 else
421 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
422 ptr += itemEncodedLen;
423 decoded += itemEncodedLen;
424 items[i].size = items[i].minSize;
427 else if (items[i].optional)
429 TRACE("skipping optional item %d\n", i);
430 items[i].size = items[i].minSize;
432 else
434 TRACE("item %d: tag %02x doesn't match expected %02x\n",
435 i, ptr[0], items[i].tag);
436 SetLastError(CRYPT_E_ASN1_BADTAG);
437 ret = FALSE;
441 else if (items[i].optional)
443 TRACE("missing optional item %d, skipping\n", i);
444 items[i].size = items[i].minSize;
446 else
448 TRACE("not enough bytes for item %d, failing\n", i);
449 SetLastError(CRYPT_E_ASN1_CORRUPT);
450 ret = FALSE;
453 if (cbDecoded)
454 *cbDecoded = decoded;
455 TRACE("returning %d\n", ret);
456 return ret;
459 /* This decodes an arbitrary sequence into a contiguous block of memory
460 * (basically, a struct.) Each element being decoded is described by a struct
461 * AsnDecodeSequenceItem, see above.
462 * startingPointer is an optional pointer to the first place where dynamic
463 * data will be stored. If you know the starting offset, you may pass it
464 * here. Otherwise, pass NULL, and one will be inferred from the items.
466 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
467 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
468 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
469 DWORD *pcbDecoded, void *startingPointer)
471 BOOL ret;
473 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
474 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
475 startingPointer);
477 if (!cbEncoded)
479 SetLastError(CRYPT_E_ASN1_EOD);
480 return FALSE;
482 if (pbEncoded[0] == ASN_SEQUENCE)
484 DWORD dataLen;
486 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
488 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
489 const BYTE *ptr = pbEncoded + 1 + lenBytes;
490 BOOL indefinite = FALSE;
492 cbEncoded -= 1 + lenBytes;
493 if (dataLen == CMSG_INDEFINITE_LENGTH)
495 dataLen = cbEncoded;
496 indefinite = TRUE;
498 else if (cbEncoded < dataLen)
500 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
501 cbEncoded);
502 SetLastError(CRYPT_E_ASN1_CORRUPT);
503 ret = FALSE;
505 if (ret)
507 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
508 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
509 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
511 if (cbDecoded > cbEncoded - 2)
513 /* Not enough space for 0 TLV */
514 SetLastError(CRYPT_E_ASN1_CORRUPT);
515 ret = FALSE;
517 else if (*(ptr + cbDecoded) != 0 ||
518 *(ptr + cbDecoded + 1) != 0)
520 TRACE("expected 0 TLV\n");
521 SetLastError(CRYPT_E_ASN1_CORRUPT);
522 ret = FALSE;
524 else
525 cbDecoded += 2;
528 if (ret && !indefinite && cbDecoded != dataLen)
530 TRACE("expected %d decoded, got %d, failing\n", dataLen,
531 cbDecoded);
532 SetLastError(CRYPT_E_ASN1_CORRUPT);
533 ret = FALSE;
535 if (ret)
537 DWORD i, bytesNeeded = 0, structSize = 0;
539 for (i = 0; i < cItem; i++)
541 bytesNeeded += items[i].size;
542 structSize += items[i].minSize;
544 if (pcbDecoded)
545 *pcbDecoded = 1 + lenBytes + cbDecoded;
546 if (!pvStructInfo)
547 *pcbStructInfo = bytesNeeded;
548 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
549 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
551 BYTE *nextData;
553 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
554 pvStructInfo = *(BYTE **)pvStructInfo;
555 if (startingPointer)
556 nextData = (BYTE *)startingPointer;
557 else
558 nextData = (BYTE *)pvStructInfo + structSize;
559 memset(pvStructInfo, 0, structSize);
560 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
561 ptr, dataLen, dwFlags, pvStructInfo, nextData,
562 &cbDecoded);
563 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
564 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
569 else
571 SetLastError(CRYPT_E_ASN1_BADTAG);
572 ret = FALSE;
574 TRACE("returning %d (%08x)\n", ret, GetLastError());
575 return ret;
578 /* tag:
579 * The expected tag of the entire encoded array (usually a variant
580 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
581 * regardless of the tag seen.
582 * decodeFunc:
583 * used to decode each item in the array
584 * itemSize:
585 * is the minimum size of each decoded item
586 * hasPointer:
587 * indicates whether each item has a dynamic pointer
588 * pointerOffset:
589 * indicates the offset within itemSize at which the pointer exists
591 struct AsnArrayDescriptor
593 BYTE tag;
594 InternalDecodeFunc decodeFunc;
595 DWORD itemSize;
596 BOOL hasPointer;
597 DWORD pointerOffset;
600 struct AsnArrayItemSize
602 DWORD encodedLen;
603 DWORD size;
606 /* Decodes an array of like types into a struct GenericArray.
607 * The layout and decoding of the array are described by a struct
608 * AsnArrayDescriptor.
610 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
611 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
612 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
613 DWORD *pcbDecoded, void *startingPointer)
615 BOOL ret = TRUE;
617 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
618 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
619 startingPointer);
621 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
623 DWORD dataLen;
625 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
627 DWORD bytesNeeded, cItems = 0, decoded;
628 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
629 /* There can be arbitrarily many items, but there is often only one.
631 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
633 decoded = 1 + lenBytes;
634 bytesNeeded = sizeof(struct GenericArray);
635 if (dataLen)
637 const BYTE *ptr;
638 BOOL doneDecoding = FALSE;
640 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
642 if (dataLen == CMSG_INDEFINITE_LENGTH)
644 if (ptr[0] == 0)
646 doneDecoding = TRUE;
647 if (ptr[1] != 0)
649 SetLastError(CRYPT_E_ASN1_CORRUPT);
650 ret = FALSE;
652 else
653 decoded += 2;
656 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
657 doneDecoding = TRUE;
658 if (!doneDecoding)
660 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
662 /* Each item decoded may not tolerate extraneous bytes,
663 * so get the length of the next element if known.
665 if ((ret = CRYPT_GetLengthIndefinite(ptr,
666 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
668 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
669 itemEncoded = cbEncoded - (ptr - pbEncoded);
670 else
671 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
672 itemDataLen;
674 if (ret)
675 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
676 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
677 &itemDecoded);
678 if (ret)
680 cItems++;
681 if (itemSizes != &itemSize)
682 itemSizes = CryptMemRealloc(itemSizes,
683 cItems * sizeof(struct AsnArrayItemSize));
684 else if (cItems > 1)
686 itemSizes =
687 CryptMemAlloc(
688 cItems * sizeof(struct AsnArrayItemSize));
689 if (itemSizes)
690 memcpy(itemSizes, &itemSize,
691 sizeof(itemSize));
693 if (itemSizes)
695 decoded += itemDecoded;
696 itemSizes[cItems - 1].encodedLen = itemEncoded;
697 itemSizes[cItems - 1].size = size;
698 bytesNeeded += size;
699 ptr += itemEncoded;
701 else
702 ret = FALSE;
707 if (ret)
709 if (pcbDecoded)
710 *pcbDecoded = decoded;
711 if (!pvStructInfo)
712 *pcbStructInfo = bytesNeeded;
713 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
714 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
716 DWORD i;
717 BYTE *nextData;
718 const BYTE *ptr;
719 struct GenericArray *array;
721 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
722 pvStructInfo = *(BYTE **)pvStructInfo;
723 array = (struct GenericArray *)pvStructInfo;
724 array->cItems = cItems;
725 if (startingPointer)
726 array->rgItems = startingPointer;
727 else
728 array->rgItems = (BYTE *)array +
729 sizeof(struct GenericArray);
730 nextData = array->rgItems +
731 array->cItems * arrayDesc->itemSize;
732 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
733 i < cItems && ptr - pbEncoded - 1 - lenBytes <
734 dataLen; i++)
736 DWORD itemDecoded;
738 if (arrayDesc->hasPointer)
739 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
740 + arrayDesc->pointerOffset) = nextData;
741 ret = arrayDesc->decodeFunc(ptr,
742 itemSizes[i].encodedLen,
743 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
744 array->rgItems + i * arrayDesc->itemSize,
745 &itemSizes[i].size, &itemDecoded);
746 if (ret)
748 nextData += itemSizes[i].size - arrayDesc->itemSize;
749 ptr += itemDecoded;
752 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
753 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
756 if (itemSizes != &itemSize)
757 CryptMemFree(itemSizes);
760 else
762 SetLastError(CRYPT_E_ASN1_BADTAG);
763 ret = FALSE;
765 return ret;
768 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
769 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
770 * to CRYPT_E_ASN1_CORRUPT.
771 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
772 * set!
774 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
775 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
777 BOOL ret;
778 DWORD dataLen;
780 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
782 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
783 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
785 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
786 bytesNeeded += 1 + lenBytes + dataLen;
788 if (pcbDecoded)
789 *pcbDecoded = 1 + lenBytes + dataLen;
790 if (!pvStructInfo)
791 *pcbStructInfo = bytesNeeded;
792 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
794 CRYPT_DER_BLOB *blob;
796 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
797 pvStructInfo = *(BYTE **)pvStructInfo;
798 blob = (CRYPT_DER_BLOB *)pvStructInfo;
799 blob->cbData = 1 + lenBytes + dataLen;
800 if (blob->cbData)
802 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
803 blob->pbData = (BYTE *)pbEncoded;
804 else
806 assert(blob->pbData);
807 memcpy(blob->pbData, pbEncoded, blob->cbData);
810 else
812 SetLastError(CRYPT_E_ASN1_CORRUPT);
813 ret = FALSE;
817 return ret;
820 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
821 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
822 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
823 DWORD *pcbDecoded)
825 BOOL ret;
827 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
828 pvStructInfo, *pcbStructInfo, pcbDecoded);
830 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
831 * place.
833 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
834 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
835 pcbDecoded);
836 if (ret && pvStructInfo)
838 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
840 if (blob->cbData)
842 DWORD i;
843 BYTE temp;
845 for (i = 0; i < blob->cbData / 2; i++)
847 temp = blob->pbData[i];
848 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
849 blob->pbData[blob->cbData - i - 1] = temp;
853 TRACE("returning %d (%08x)\n", ret, GetLastError());
854 return ret;
857 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
858 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
859 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
861 BOOL ret = TRUE;
863 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
864 pDecodePara, pvStructInfo, *pcbStructInfo);
866 __TRY
868 struct AsnDecodeSequenceItem items[] = {
869 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
870 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
871 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
872 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
873 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
874 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
875 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
876 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
877 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
878 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
881 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
882 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
883 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
884 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
885 pcbStructInfo, NULL, NULL);
887 __EXCEPT_PAGE_FAULT
889 SetLastError(STATUS_ACCESS_VIOLATION);
890 ret = FALSE;
892 __ENDTRY
894 TRACE("Returning %d (%08x)\n", ret, GetLastError());
895 return ret;
898 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
899 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
901 BOOL ret;
902 DWORD dataLen;
904 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
906 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
908 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
909 dwFlags, pvStructInfo, pcbStructInfo, NULL);
910 if (pcbDecoded)
911 *pcbDecoded = 1 + lenBytes + dataLen;
913 return ret;
916 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
917 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
919 BOOL ret;
921 struct AsnDecodeSequenceItem items[] = {
922 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
923 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
924 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
925 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
928 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
929 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
930 pcbDecoded, NULL);
931 return ret;
934 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
935 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
936 DWORD *pcbDecoded)
938 BOOL ret;
939 DWORD dataLen;
941 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
943 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
945 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
946 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
947 if (ret && pcbDecoded)
948 *pcbDecoded = 1 + lenBytes + dataLen;
950 return ret;
953 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
954 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
955 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
957 BOOL ret = TRUE;
958 struct AsnDecodeSequenceItem items[] = {
959 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
960 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
961 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
962 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
963 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
964 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
965 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
966 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
967 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
968 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
969 Issuer.pbData) },
970 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
971 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
972 FALSE, 0 },
973 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
974 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
975 Subject.pbData) },
976 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
977 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
978 FALSE, TRUE, offsetof(CERT_INFO,
979 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
980 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
981 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
982 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
983 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
984 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
985 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
986 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
987 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
988 offsetof(CERT_INFO, rgExtension), 0 },
991 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
992 pDecodePara, pvStructInfo, *pcbStructInfo);
994 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
995 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
996 NULL, NULL);
997 if (ret && pvStructInfo)
999 CERT_INFO *info;
1001 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1002 info = *(CERT_INFO **)pvStructInfo;
1003 else
1004 info = (CERT_INFO *)pvStructInfo;
1005 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1006 !info->Subject.cbData)
1008 SetLastError(CRYPT_E_ASN1_CORRUPT);
1009 /* Don't need to deallocate, because it should have failed on the
1010 * first pass (and no memory was allocated.)
1012 ret = FALSE;
1016 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1017 return ret;
1020 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1021 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1022 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1024 BOOL ret = FALSE;
1026 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1027 pDecodePara, pvStructInfo, *pcbStructInfo);
1029 __TRY
1031 DWORD size = 0;
1033 /* Unless told not to, first try to decode it as a signed cert. */
1034 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1036 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1038 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1039 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1040 (BYTE *)&signedCert, &size);
1041 if (ret)
1043 size = 0;
1044 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1045 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1046 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1047 pvStructInfo, pcbStructInfo);
1048 LocalFree(signedCert);
1051 /* Failing that, try it as an unsigned cert */
1052 if (!ret)
1054 size = 0;
1055 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1056 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1057 pDecodePara, pvStructInfo, pcbStructInfo);
1060 __EXCEPT_PAGE_FAULT
1062 SetLastError(STATUS_ACCESS_VIOLATION);
1064 __ENDTRY
1066 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1067 return ret;
1070 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1071 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1073 BOOL ret;
1074 struct AsnDecodeSequenceItem items[] = {
1075 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1076 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1077 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1078 { 0, offsetof(CRL_ENTRY, RevocationDate),
1079 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1080 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1081 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1082 offsetof(CRL_ENTRY, rgExtension), 0 },
1084 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1086 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1087 *pcbStructInfo);
1089 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1090 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1091 entry ? entry->SerialNumber.pbData : NULL);
1092 if (ret && entry && !entry->SerialNumber.cbData)
1094 WARN("empty CRL entry serial number\n");
1095 SetLastError(CRYPT_E_ASN1_CORRUPT);
1096 ret = FALSE;
1098 return ret;
1101 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1102 * been set prior to calling.
1104 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1105 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1107 BOOL ret;
1108 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1109 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1110 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1111 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1113 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1114 pvStructInfo, *pcbStructInfo, pcbDecoded);
1116 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1117 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1118 entries ? entries->rgItems : NULL);
1119 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1120 return ret;
1123 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1124 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1125 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1127 struct AsnDecodeSequenceItem items[] = {
1128 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1129 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1130 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1131 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1132 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1133 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1134 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1135 Issuer.pbData) },
1136 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1137 sizeof(FILETIME), FALSE, FALSE, 0 },
1138 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1139 sizeof(FILETIME), TRUE, FALSE, 0 },
1140 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1141 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1142 offsetof(CRL_INFO, rgCRLEntry), 0 },
1143 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1144 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1145 offsetof(CRL_INFO, rgExtension), 0 },
1147 BOOL ret = TRUE;
1149 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1150 pDecodePara, pvStructInfo, *pcbStructInfo);
1152 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1153 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1154 NULL, NULL);
1156 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1157 return ret;
1160 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1161 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1162 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1164 BOOL ret = FALSE;
1166 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1167 pDecodePara, pvStructInfo, *pcbStructInfo);
1169 __TRY
1171 DWORD size = 0;
1173 /* Unless told not to, first try to decode it as a signed crl. */
1174 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1176 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1178 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1179 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1180 (BYTE *)&signedCrl, &size);
1181 if (ret)
1183 size = 0;
1184 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1185 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1186 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1187 pvStructInfo, pcbStructInfo);
1188 LocalFree(signedCrl);
1191 /* Failing that, try it as an unsigned crl */
1192 if (!ret)
1194 size = 0;
1195 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1196 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1197 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1200 __EXCEPT_PAGE_FAULT
1202 SetLastError(STATUS_ACCESS_VIOLATION);
1204 __ENDTRY
1206 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1207 return ret;
1210 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1211 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1213 BOOL ret = TRUE;
1214 DWORD dataLen;
1216 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1217 pvStructInfo, *pcbStructInfo);
1219 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1221 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1222 DWORD bytesNeeded = sizeof(LPSTR);
1224 if (dataLen)
1226 /* The largest possible string for the first two components
1227 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1229 char firstTwo[6];
1230 const BYTE *ptr;
1232 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1233 pbEncoded[1 + lenBytes] / 40,
1234 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1235 * 40);
1236 bytesNeeded += strlen(firstTwo) + 1;
1237 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1238 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1240 /* large enough for ".4000000" */
1241 char str[9];
1242 int val = 0;
1244 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1245 (*ptr & 0x80))
1247 val <<= 7;
1248 val |= *ptr & 0x7f;
1249 ptr++;
1251 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1252 (*ptr & 0x80))
1254 SetLastError(CRYPT_E_ASN1_CORRUPT);
1255 ret = FALSE;
1257 else
1259 val <<= 7;
1260 val |= *ptr++;
1261 snprintf(str, sizeof(str), ".%d", val);
1262 bytesNeeded += strlen(str);
1266 if (pcbDecoded)
1267 *pcbDecoded = 1 + lenBytes + dataLen;
1268 if (!pvStructInfo)
1269 *pcbStructInfo = bytesNeeded;
1270 else if (*pcbStructInfo < bytesNeeded)
1272 *pcbStructInfo = bytesNeeded;
1273 SetLastError(ERROR_MORE_DATA);
1274 ret = FALSE;
1276 else
1278 if (dataLen)
1280 const BYTE *ptr;
1281 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1283 *pszObjId = 0;
1284 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1285 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1286 40) * 40);
1287 pszObjId += strlen(pszObjId);
1288 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1289 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1291 int val = 0;
1293 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1294 (*ptr & 0x80))
1296 val <<= 7;
1297 val |= *ptr & 0x7f;
1298 ptr++;
1300 val <<= 7;
1301 val |= *ptr++;
1302 sprintf(pszObjId, ".%d", val);
1303 pszObjId += strlen(pszObjId);
1306 else
1307 *(LPSTR *)pvStructInfo = NULL;
1308 *pcbStructInfo = bytesNeeded;
1311 return ret;
1314 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1315 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1317 BOOL ret;
1319 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1320 pvStructInfo, *pcbStructInfo);
1322 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1323 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1324 pvStructInfo, pcbStructInfo, pcbDecoded);
1325 else
1327 SetLastError(CRYPT_E_ASN1_BADTAG);
1328 ret = FALSE;
1330 return ret;
1333 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1334 * ahead of time!
1336 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1337 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1339 struct AsnDecodeSequenceItem items[] = {
1340 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1341 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1342 offsetof(CERT_EXTENSION, pszObjId), 0 },
1343 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1344 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1345 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1346 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1347 offsetof(CERT_EXTENSION, Value.pbData) },
1349 BOOL ret = TRUE;
1350 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1352 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1353 *pcbStructInfo);
1355 if (ext)
1356 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1357 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1358 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1359 pcbDecoded, ext ? ext->pszObjId : NULL);
1360 if (ext)
1361 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1362 debugstr_a(ext->pszObjId));
1363 TRACE("returning %d (%08x)\n", ret, GetLastError());
1364 return ret;
1367 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1368 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1369 DWORD *pcbDecoded)
1371 BOOL ret = TRUE;
1372 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1373 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1374 offsetof(CERT_EXTENSION, pszObjId) };
1375 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1377 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1378 pvStructInfo, *pcbStructInfo, pcbDecoded);
1380 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1381 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1382 exts ? exts->rgExtension : NULL);
1383 return ret;
1386 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1387 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1388 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1390 BOOL ret = TRUE;
1392 __TRY
1394 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1395 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1396 if (ret && pvStructInfo)
1398 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1399 pcbStructInfo, *pcbStructInfo);
1400 if (ret)
1402 CERT_EXTENSIONS *exts;
1404 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1405 pvStructInfo = *(BYTE **)pvStructInfo;
1406 exts = (CERT_EXTENSIONS *)pvStructInfo;
1407 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1408 sizeof(CERT_EXTENSIONS));
1409 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1410 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1411 pcbStructInfo, NULL);
1415 __EXCEPT_PAGE_FAULT
1417 SetLastError(STATUS_ACCESS_VIOLATION);
1418 ret = FALSE;
1420 __ENDTRY
1421 return ret;
1424 /* Warning: this assumes the address of value->Value.pbData is already set, in
1425 * order to avoid overwriting memory. (In some cases, it may change it, if it
1426 * doesn't copy anything to memory.) Be sure to set it correctly!
1428 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1429 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1430 DWORD *pcbDecoded)
1432 BOOL ret = TRUE;
1433 DWORD dataLen;
1434 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1436 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1438 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1439 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1441 switch (pbEncoded[0])
1443 case ASN_OCTETSTRING:
1444 valueType = CERT_RDN_OCTET_STRING;
1445 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1446 bytesNeeded += dataLen;
1447 break;
1448 case ASN_NUMERICSTRING:
1449 valueType = CERT_RDN_NUMERIC_STRING;
1450 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1451 bytesNeeded += dataLen;
1452 break;
1453 case ASN_PRINTABLESTRING:
1454 valueType = CERT_RDN_PRINTABLE_STRING;
1455 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1456 bytesNeeded += dataLen;
1457 break;
1458 case ASN_IA5STRING:
1459 valueType = CERT_RDN_IA5_STRING;
1460 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1461 bytesNeeded += dataLen;
1462 break;
1463 case ASN_T61STRING:
1464 valueType = CERT_RDN_T61_STRING;
1465 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1466 bytesNeeded += dataLen;
1467 break;
1468 case ASN_VIDEOTEXSTRING:
1469 valueType = CERT_RDN_VIDEOTEX_STRING;
1470 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1471 bytesNeeded += dataLen;
1472 break;
1473 case ASN_GRAPHICSTRING:
1474 valueType = CERT_RDN_GRAPHIC_STRING;
1475 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1476 bytesNeeded += dataLen;
1477 break;
1478 case ASN_VISIBLESTRING:
1479 valueType = CERT_RDN_VISIBLE_STRING;
1480 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1481 bytesNeeded += dataLen;
1482 break;
1483 case ASN_GENERALSTRING:
1484 valueType = CERT_RDN_GENERAL_STRING;
1485 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1486 bytesNeeded += dataLen;
1487 break;
1488 case ASN_UNIVERSALSTRING:
1489 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1490 SetLastError(CRYPT_E_ASN1_BADTAG);
1491 return FALSE;
1492 case ASN_BMPSTRING:
1493 valueType = CERT_RDN_BMP_STRING;
1494 bytesNeeded += dataLen;
1495 break;
1496 case ASN_UTF8STRING:
1497 valueType = CERT_RDN_UTF8_STRING;
1498 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1499 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1500 break;
1501 default:
1502 SetLastError(CRYPT_E_ASN1_BADTAG);
1503 return FALSE;
1506 if (pcbDecoded)
1507 *pcbDecoded = 1 + lenBytes + dataLen;
1508 if (!value)
1509 *pcbStructInfo = bytesNeeded;
1510 else if (*pcbStructInfo < bytesNeeded)
1512 *pcbStructInfo = bytesNeeded;
1513 SetLastError(ERROR_MORE_DATA);
1514 ret = FALSE;
1516 else
1518 *pcbStructInfo = bytesNeeded;
1519 value->dwValueType = valueType;
1520 if (dataLen)
1522 DWORD i;
1524 assert(value->Value.pbData);
1525 switch (pbEncoded[0])
1527 case ASN_OCTETSTRING:
1528 case ASN_NUMERICSTRING:
1529 case ASN_PRINTABLESTRING:
1530 case ASN_IA5STRING:
1531 case ASN_T61STRING:
1532 case ASN_VIDEOTEXSTRING:
1533 case ASN_GRAPHICSTRING:
1534 case ASN_VISIBLESTRING:
1535 case ASN_GENERALSTRING:
1536 value->Value.cbData = dataLen;
1537 if (dataLen)
1539 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1540 memcpy(value->Value.pbData,
1541 pbEncoded + 1 + lenBytes, dataLen);
1542 else
1543 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1544 lenBytes;
1546 break;
1547 case ASN_BMPSTRING:
1549 LPWSTR str = (LPWSTR)value->Value.pbData;
1551 value->Value.cbData = dataLen;
1552 for (i = 0; i < dataLen / 2; i++)
1553 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1554 pbEncoded[1 + lenBytes + 2 * i + 1];
1555 break;
1557 case ASN_UTF8STRING:
1559 LPWSTR str = (LPWSTR)value->Value.pbData;
1561 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1562 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1563 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1564 break;
1568 else
1570 value->Value.cbData = 0;
1571 value->Value.pbData = NULL;
1575 return ret;
1578 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1579 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1580 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1582 BOOL ret = TRUE;
1584 __TRY
1586 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1587 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1588 if (ret && pvStructInfo)
1590 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1591 pcbStructInfo, *pcbStructInfo);
1592 if (ret)
1594 CERT_NAME_VALUE *value;
1596 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1597 pvStructInfo = *(BYTE **)pvStructInfo;
1598 value = (CERT_NAME_VALUE *)pvStructInfo;
1599 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1600 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1601 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1602 pcbStructInfo, NULL);
1606 __EXCEPT_PAGE_FAULT
1608 SetLastError(STATUS_ACCESS_VIOLATION);
1609 ret = FALSE;
1611 __ENDTRY
1612 return ret;
1615 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1616 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1617 DWORD *pcbDecoded)
1619 BOOL ret = TRUE;
1620 DWORD dataLen;
1621 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1623 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1625 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1626 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1628 switch (pbEncoded[0])
1630 case ASN_NUMERICSTRING:
1631 valueType = CERT_RDN_NUMERIC_STRING;
1632 bytesNeeded += dataLen * 2;
1633 break;
1634 case ASN_PRINTABLESTRING:
1635 valueType = CERT_RDN_PRINTABLE_STRING;
1636 bytesNeeded += dataLen * 2;
1637 break;
1638 case ASN_IA5STRING:
1639 valueType = CERT_RDN_IA5_STRING;
1640 bytesNeeded += dataLen * 2;
1641 break;
1642 case ASN_T61STRING:
1643 valueType = CERT_RDN_T61_STRING;
1644 bytesNeeded += dataLen * 2;
1645 break;
1646 case ASN_VIDEOTEXSTRING:
1647 valueType = CERT_RDN_VIDEOTEX_STRING;
1648 bytesNeeded += dataLen * 2;
1649 break;
1650 case ASN_GRAPHICSTRING:
1651 valueType = CERT_RDN_GRAPHIC_STRING;
1652 bytesNeeded += dataLen * 2;
1653 break;
1654 case ASN_VISIBLESTRING:
1655 valueType = CERT_RDN_VISIBLE_STRING;
1656 bytesNeeded += dataLen * 2;
1657 break;
1658 case ASN_GENERALSTRING:
1659 valueType = CERT_RDN_GENERAL_STRING;
1660 bytesNeeded += dataLen * 2;
1661 break;
1662 case ASN_UNIVERSALSTRING:
1663 valueType = CERT_RDN_UNIVERSAL_STRING;
1664 bytesNeeded += dataLen / 2;
1665 break;
1666 case ASN_BMPSTRING:
1667 valueType = CERT_RDN_BMP_STRING;
1668 bytesNeeded += dataLen;
1669 break;
1670 case ASN_UTF8STRING:
1671 valueType = CERT_RDN_UTF8_STRING;
1672 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1673 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1674 break;
1675 default:
1676 SetLastError(CRYPT_E_ASN1_BADTAG);
1677 return FALSE;
1680 if (pcbDecoded)
1681 *pcbDecoded = 1 + lenBytes + dataLen;
1682 if (!value)
1683 *pcbStructInfo = bytesNeeded;
1684 else if (*pcbStructInfo < bytesNeeded)
1686 *pcbStructInfo = bytesNeeded;
1687 SetLastError(ERROR_MORE_DATA);
1688 ret = FALSE;
1690 else
1692 *pcbStructInfo = bytesNeeded;
1693 value->dwValueType = valueType;
1694 if (dataLen)
1696 DWORD i;
1697 LPWSTR str = (LPWSTR)value->Value.pbData;
1699 assert(value->Value.pbData);
1700 switch (pbEncoded[0])
1702 case ASN_NUMERICSTRING:
1703 case ASN_PRINTABLESTRING:
1704 case ASN_IA5STRING:
1705 case ASN_T61STRING:
1706 case ASN_VIDEOTEXSTRING:
1707 case ASN_GRAPHICSTRING:
1708 case ASN_VISIBLESTRING:
1709 case ASN_GENERALSTRING:
1710 value->Value.cbData = dataLen * 2;
1711 for (i = 0; i < dataLen; i++)
1712 str[i] = pbEncoded[1 + lenBytes + i];
1713 break;
1714 case ASN_UNIVERSALSTRING:
1715 value->Value.cbData = dataLen / 2;
1716 for (i = 0; i < dataLen / 4; i++)
1717 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1718 | pbEncoded[1 + lenBytes + 2 * i + 3];
1719 break;
1720 case ASN_BMPSTRING:
1721 value->Value.cbData = dataLen;
1722 for (i = 0; i < dataLen / 2; i++)
1723 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1724 pbEncoded[1 + lenBytes + 2 * i + 1];
1725 break;
1726 case ASN_UTF8STRING:
1727 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1728 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1729 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1730 break;
1733 else
1735 value->Value.cbData = 0;
1736 value->Value.pbData = NULL;
1740 return ret;
1743 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1744 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1745 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1747 BOOL ret = TRUE;
1749 __TRY
1751 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1752 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1753 if (ret && pvStructInfo)
1755 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1756 pcbStructInfo, *pcbStructInfo);
1757 if (ret)
1759 CERT_NAME_VALUE *value;
1761 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1762 pvStructInfo = *(BYTE **)pvStructInfo;
1763 value = (CERT_NAME_VALUE *)pvStructInfo;
1764 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1765 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1766 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1767 pcbStructInfo, NULL);
1771 __EXCEPT_PAGE_FAULT
1773 SetLastError(STATUS_ACCESS_VIOLATION);
1774 ret = FALSE;
1776 __ENDTRY
1777 return ret;
1780 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1781 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1783 BOOL ret;
1784 struct AsnDecodeSequenceItem items[] = {
1785 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1786 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1787 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1788 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1789 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1790 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1792 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1794 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1795 pvStructInfo, *pcbStructInfo);
1797 if (attr)
1798 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1799 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1800 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1801 attr ? attr->pszObjId : NULL);
1802 if (attr)
1804 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1805 debugstr_a(attr->pszObjId));
1806 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1808 TRACE("returning %d (%08x)\n", ret, GetLastError());
1809 return ret;
1812 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1813 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1815 BOOL ret = TRUE;
1816 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1817 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1818 offsetof(CERT_RDN_ATTR, pszObjId) };
1819 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1821 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1822 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1823 rdn ? rdn->rgRDNAttr : NULL);
1824 return ret;
1827 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1828 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1829 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1831 BOOL ret = TRUE;
1833 __TRY
1835 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1836 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1837 offsetof(CERT_RDN, rgRDNAttr) };
1839 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1840 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1842 __EXCEPT_PAGE_FAULT
1844 SetLastError(STATUS_ACCESS_VIOLATION);
1845 ret = FALSE;
1847 __ENDTRY
1848 return ret;
1851 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1852 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1853 DWORD *pcbDecoded)
1855 BOOL ret;
1856 struct AsnDecodeSequenceItem items[] = {
1857 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1858 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1859 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1860 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1861 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1862 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1864 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1866 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1867 pvStructInfo, *pcbStructInfo);
1869 if (attr)
1870 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1871 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1872 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1873 attr ? attr->pszObjId : NULL);
1874 if (attr)
1876 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1877 debugstr_a(attr->pszObjId));
1878 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1880 TRACE("returning %d (%08x)\n", ret, GetLastError());
1881 return ret;
1884 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1885 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1887 BOOL ret = TRUE;
1888 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1889 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1890 offsetof(CERT_RDN_ATTR, pszObjId) };
1891 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1893 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1894 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1895 rdn ? rdn->rgRDNAttr : NULL);
1896 return ret;
1899 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1900 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1901 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1903 BOOL ret = TRUE;
1905 __TRY
1907 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1908 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1909 offsetof(CERT_RDN, rgRDNAttr) };
1911 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1912 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1914 __EXCEPT_PAGE_FAULT
1916 SetLastError(STATUS_ACCESS_VIOLATION);
1917 ret = FALSE;
1919 __ENDTRY
1920 return ret;
1923 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1924 DWORD *pcbDecoded)
1926 BOOL ret = TRUE, done = FALSE;
1927 DWORD indefiniteNestingLevels = 0, decoded = 0;
1929 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1931 do {
1932 DWORD dataLen;
1934 if (!cbEncoded)
1935 done = TRUE;
1936 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
1937 &dataLen)))
1939 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1941 if (dataLen == CMSG_INDEFINITE_LENGTH)
1943 indefiniteNestingLevels++;
1944 pbEncoded += 1 + lenBytes;
1945 cbEncoded -= 1 + lenBytes;
1946 decoded += 1 + lenBytes;
1947 TRACE("indefiniteNestingLevels = %d\n",
1948 indefiniteNestingLevels);
1950 else
1952 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
1953 indefiniteNestingLevels)
1955 indefiniteNestingLevels--;
1956 TRACE("indefiniteNestingLevels = %d\n",
1957 indefiniteNestingLevels);
1959 pbEncoded += 1 + lenBytes + dataLen;
1960 cbEncoded -= 1 + lenBytes + dataLen;
1961 decoded += 1 + lenBytes + dataLen;
1962 if (!indefiniteNestingLevels)
1963 done = TRUE;
1966 } while (ret && !done);
1967 /* If we haven't found all 0 TLVs, we haven't found the end */
1968 if (ret && indefiniteNestingLevels)
1970 SetLastError(CRYPT_E_ASN1_EOD);
1971 ret = FALSE;
1973 if (ret)
1974 *pcbDecoded = decoded;
1975 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
1976 return ret;
1979 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1980 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1981 DWORD *pcbDecoded)
1983 BOOL ret = TRUE;
1984 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
1986 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1987 pvStructInfo, *pcbStructInfo);
1989 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
1991 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1992 bytesNeeded += encodedLen;
1993 if (!pvStructInfo)
1994 *pcbStructInfo = bytesNeeded;
1995 else if (*pcbStructInfo < bytesNeeded)
1997 SetLastError(ERROR_MORE_DATA);
1998 *pcbStructInfo = bytesNeeded;
1999 ret = FALSE;
2001 else
2003 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
2005 *pcbStructInfo = bytesNeeded;
2006 blob->cbData = encodedLen;
2007 if (encodedLen)
2009 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2010 blob->pbData = (LPBYTE)pbEncoded;
2011 else
2013 assert(blob->pbData);
2014 memcpy(blob->pbData, pbEncoded, blob->cbData);
2017 else
2018 blob->pbData = NULL;
2020 if (pcbDecoded)
2021 *pcbDecoded = encodedLen;
2023 return ret;
2026 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
2027 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2029 BOOL ret;
2030 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
2031 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2032 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
2034 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2035 pvStructInfo, *pcbStructInfo, pcbDecoded);
2037 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2038 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2039 array ? array->rgItems : NULL);
2040 return ret;
2043 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2044 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2046 BOOL ret;
2047 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2048 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2049 CTL_USAGE *usage = (CTL_USAGE *)pvStructInfo;
2051 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2052 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2053 usage ? usage->rgpszUsageIdentifier : NULL);
2054 return ret;
2057 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2058 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2060 struct AsnDecodeSequenceItem items[] = {
2061 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2062 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2063 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2064 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2065 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), FALSE,
2066 TRUE, offsetof(CTL_ENTRY, rgAttribute), 0 },
2068 BOOL ret = TRUE;
2069 CTL_ENTRY *entry = (CTL_ENTRY *)pvStructInfo;
2071 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2072 *pcbStructInfo);
2074 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2075 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2076 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2077 return ret;
2080 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2081 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2083 BOOL ret;
2084 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2085 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2086 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2087 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2089 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2090 pvStructInfo, *pcbStructInfo, pcbDecoded);
2092 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2093 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2094 entries ? entries->rgItems : NULL);
2095 return ret;
2098 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2099 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2100 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2102 BOOL ret = FALSE;
2104 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2105 pDecodePara, pvStructInfo, *pcbStructInfo);
2107 __TRY
2109 struct AsnDecodeSequenceItem items[] = {
2110 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2111 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2112 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2113 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2114 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2115 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2116 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
2117 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2118 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2119 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2120 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2121 { 0, offsetof(CTL_INFO, ThisUpdate),
2122 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2123 0 },
2124 { 0, offsetof(CTL_INFO, NextUpdate),
2125 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2126 0 },
2127 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2128 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2129 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2130 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2131 CRYPT_AsnDecodeCTLEntries, sizeof(struct GenericArray),
2132 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2133 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2134 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
2135 offsetof(CTL_INFO, rgExtension), 0 },
2138 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2139 pDecodePara, pvStructInfo, *pcbStructInfo);
2141 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2142 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2143 pcbStructInfo, NULL, NULL);
2145 __EXCEPT_PAGE_FAULT
2147 SetLastError(STATUS_ACCESS_VIOLATION);
2149 __ENDTRY
2150 return ret;
2153 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2154 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2155 DWORD *pcbDecoded)
2157 BOOL ret;
2158 struct AsnDecodeSequenceItem items[] = {
2159 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2160 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2161 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2162 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2163 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2164 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2166 PCRYPT_SMIME_CAPABILITY capability = (PCRYPT_SMIME_CAPABILITY)pvStructInfo;
2168 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2169 pvStructInfo, *pcbStructInfo);
2171 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2172 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2173 pcbDecoded, capability ? capability->pszObjId : NULL);
2174 TRACE("returning %d\n", ret);
2175 return ret;
2178 static BOOL CRYPT_AsnDecodeSMIMECapabilitiesInternal(const BYTE *pbEncoded,
2179 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2180 DWORD *pcbDecoded)
2182 struct AsnArrayDescriptor arrayDesc = { 0,
2183 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2184 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2185 PCRYPT_SMIME_CAPABILITIES capabilities =
2186 (PCRYPT_SMIME_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 = (PCRYPT_SMIME_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_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2245 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2246 DWORD *pcbDecoded)
2248 BOOL ret;
2249 struct AsnDecodeSequenceItem items[] = {
2250 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2251 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2252 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2253 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2254 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
2255 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2257 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2259 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2260 pvStructInfo, *pcbStructInfo);
2262 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2263 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2264 pcbDecoded, attr ? attr->pszObjId : NULL);
2265 TRACE("returning %d\n", ret);
2266 return ret;
2269 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2270 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2271 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2273 BOOL ret = FALSE;
2275 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2276 pDecodePara, pvStructInfo, *pcbStructInfo);
2278 __TRY
2280 DWORD bytesNeeded;
2282 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2283 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2284 if (ret)
2286 if (!pvStructInfo)
2287 *pcbStructInfo = bytesNeeded;
2288 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2289 pvStructInfo, pcbStructInfo, bytesNeeded)))
2291 PCRYPT_ATTRIBUTE attr;
2293 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2294 pvStructInfo = *(BYTE **)pvStructInfo;
2295 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2296 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2297 sizeof(CRYPT_ATTRIBUTE));
2298 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2299 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2300 NULL);
2304 __EXCEPT_PAGE_FAULT
2306 SetLastError(STATUS_ACCESS_VIOLATION);
2308 __ENDTRY
2309 TRACE("returning %d\n", ret);
2310 return ret;
2313 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2314 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2315 DWORD *pcbDecoded)
2317 struct AsnArrayDescriptor arrayDesc = { 0,
2318 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2319 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2320 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2321 BOOL ret;
2323 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2324 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2325 NULL);
2326 return ret;
2329 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2330 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2331 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2333 BOOL ret = FALSE;
2335 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2336 pDecodePara, pvStructInfo, *pcbStructInfo);
2338 __TRY
2340 DWORD bytesNeeded;
2342 if (!cbEncoded)
2343 SetLastError(CRYPT_E_ASN1_EOD);
2344 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2345 SetLastError(CRYPT_E_ASN1_CORRUPT);
2346 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2347 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2348 NULL)))
2350 if (!pvStructInfo)
2351 *pcbStructInfo = bytesNeeded;
2352 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2353 pvStructInfo, pcbStructInfo, bytesNeeded)))
2355 PCRYPT_ATTRIBUTES attrs;
2357 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2358 pvStructInfo = *(BYTE **)pvStructInfo;
2359 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2360 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2361 sizeof(CRYPT_ATTRIBUTES));
2362 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2363 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2364 &bytesNeeded, NULL);
2368 __EXCEPT_PAGE_FAULT
2370 SetLastError(STATUS_ACCESS_VIOLATION);
2372 __ENDTRY
2373 TRACE("returning %d\n", ret);
2374 return ret;
2377 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2378 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2380 CRYPT_ALGORITHM_IDENTIFIER *algo =
2381 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2382 BOOL ret = TRUE;
2383 struct AsnDecodeSequenceItem items[] = {
2384 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2385 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2386 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2387 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2388 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2389 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2392 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2393 pvStructInfo, *pcbStructInfo, pcbDecoded);
2395 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2396 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2397 pcbDecoded, algo ? algo->pszObjId : NULL);
2398 if (ret && pvStructInfo)
2400 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2401 debugstr_a(algo->pszObjId));
2403 return ret;
2406 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2407 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2408 DWORD *pcbDecoded)
2410 BOOL ret = TRUE;
2411 struct AsnDecodeSequenceItem items[] = {
2412 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2413 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2414 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2415 Algorithm.pszObjId) },
2416 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2417 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2418 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2420 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2422 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2423 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2424 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2425 return ret;
2428 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2429 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2430 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2432 BOOL ret = TRUE;
2434 __TRY
2436 DWORD bytesNeeded;
2438 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2439 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2441 if (!pvStructInfo)
2442 *pcbStructInfo = bytesNeeded;
2443 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2444 pvStructInfo, pcbStructInfo, bytesNeeded)))
2446 PCERT_PUBLIC_KEY_INFO info;
2448 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2449 pvStructInfo = *(BYTE **)pvStructInfo;
2450 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2451 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2452 sizeof(CERT_PUBLIC_KEY_INFO);
2453 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2454 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2455 &bytesNeeded, NULL);
2459 __EXCEPT_PAGE_FAULT
2461 SetLastError(STATUS_ACCESS_VIOLATION);
2462 ret = FALSE;
2464 __ENDTRY
2465 return ret;
2468 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2469 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2471 BOOL ret;
2473 if (cbEncoded < 3)
2475 SetLastError(CRYPT_E_ASN1_CORRUPT);
2476 return FALSE;
2478 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2480 SetLastError(CRYPT_E_ASN1_CORRUPT);
2481 return FALSE;
2483 if (pbEncoded[1] > 1)
2485 SetLastError(CRYPT_E_ASN1_CORRUPT);
2486 return FALSE;
2488 if (pcbDecoded)
2489 *pcbDecoded = 3;
2490 if (!pvStructInfo)
2492 *pcbStructInfo = sizeof(BOOL);
2493 ret = TRUE;
2495 else if (*pcbStructInfo < sizeof(BOOL))
2497 *pcbStructInfo = sizeof(BOOL);
2498 SetLastError(ERROR_MORE_DATA);
2499 ret = FALSE;
2501 else
2503 *pcbStructInfo = sizeof(BOOL);
2504 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2505 ret = TRUE;
2507 TRACE("returning %d (%08x)\n", ret, GetLastError());
2508 return ret;
2511 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2512 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2514 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2515 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2516 BOOL ret;
2518 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2519 pvStructInfo, *pcbStructInfo);
2521 if (cbEncoded < 2)
2523 SetLastError(CRYPT_E_ASN1_CORRUPT);
2524 return FALSE;
2526 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2527 if (1 + lenBytes > cbEncoded)
2529 SetLastError(CRYPT_E_ASN1_CORRUPT);
2530 return FALSE;
2532 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2534 switch (pbEncoded[0] & ASN_TYPE_MASK)
2536 case 1: /* rfc822Name */
2537 case 2: /* dNSName */
2538 case 6: /* uniformResourceIdentifier */
2539 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2540 break;
2541 case 4: /* directoryName */
2542 case 7: /* iPAddress */
2543 bytesNeeded += dataLen;
2544 break;
2545 case 8: /* registeredID */
2546 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2547 &dataLen, NULL);
2548 if (ret)
2550 /* FIXME: ugly, shouldn't need to know internals of OID decode
2551 * function to use it.
2553 bytesNeeded += dataLen - sizeof(LPSTR);
2555 break;
2556 case 0: /* otherName */
2557 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2558 SetLastError(CRYPT_E_ASN1_BADTAG);
2559 ret = FALSE;
2560 break;
2561 case 3: /* x400Address, unimplemented */
2562 case 5: /* ediPartyName, unimplemented */
2563 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2564 SetLastError(CRYPT_E_ASN1_BADTAG);
2565 ret = FALSE;
2566 break;
2567 default:
2568 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2569 SetLastError(CRYPT_E_ASN1_CORRUPT);
2570 ret = FALSE;
2572 if (ret)
2574 if (pcbDecoded)
2575 *pcbDecoded = 1 + lenBytes + dataLen;
2576 if (!entry)
2577 *pcbStructInfo = bytesNeeded;
2578 else if (*pcbStructInfo < bytesNeeded)
2580 *pcbStructInfo = bytesNeeded;
2581 SetLastError(ERROR_MORE_DATA);
2582 ret = FALSE;
2584 else
2586 *pcbStructInfo = bytesNeeded;
2587 /* MS used values one greater than the asn1 ones.. sigh */
2588 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
2589 switch (pbEncoded[0] & ASN_TYPE_MASK)
2591 case 1: /* rfc822Name */
2592 case 2: /* dNSName */
2593 case 6: /* uniformResourceIdentifier */
2595 DWORD i;
2597 for (i = 0; i < dataLen; i++)
2598 entry->u.pwszURL[i] =
2599 (WCHAR)pbEncoded[1 + lenBytes + i];
2600 entry->u.pwszURL[i] = 0;
2601 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2602 debugstr_w(entry->u.pwszURL));
2603 break;
2605 case 4: /* directoryName */
2606 /* The data are memory-equivalent with the IPAddress case,
2607 * fall-through
2609 case 7: /* iPAddress */
2610 /* The next data pointer is in the pwszURL spot, that is,
2611 * the first 4 bytes. Need to move it to the next spot.
2613 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2614 entry->u.IPAddress.cbData = dataLen;
2615 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2616 dataLen);
2617 break;
2618 case 8: /* registeredID */
2619 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2620 &entry->u.pszRegisteredID, &dataLen, NULL);
2621 break;
2626 return ret;
2629 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2630 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2631 DWORD *pcbDecoded)
2633 BOOL ret = TRUE;
2634 struct AsnArrayDescriptor arrayDesc = { 0,
2635 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2636 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2637 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2639 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2640 pvStructInfo, *pcbStructInfo, pcbDecoded);
2642 if (info)
2643 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2644 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2645 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2646 info ? info->rgAltEntry : NULL);
2647 return ret;
2650 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2651 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2652 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2653 DWORD *pcbDecoded)
2655 BOOL ret;
2657 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2658 pvStructInfo, *pcbStructInfo, pcbDecoded);
2660 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2661 * place.
2663 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2664 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2665 pcbDecoded);
2666 if (ret && pvStructInfo)
2668 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2670 if (blob->cbData)
2672 DWORD i;
2673 BYTE temp;
2675 for (i = 0; i < blob->cbData / 2; i++)
2677 temp = blob->pbData[i];
2678 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2679 blob->pbData[blob->cbData - i - 1] = temp;
2683 TRACE("returning %d (%08x)\n", ret, GetLastError());
2684 return ret;
2687 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2688 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2689 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2691 BOOL ret;
2693 __TRY
2695 struct AsnDecodeSequenceItem items[] = {
2696 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2697 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2698 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2699 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2700 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2701 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2702 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2703 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2704 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2705 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2706 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2709 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2710 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2711 pcbStructInfo, NULL, NULL);
2713 __EXCEPT_PAGE_FAULT
2715 SetLastError(STATUS_ACCESS_VIOLATION);
2716 ret = FALSE;
2718 __ENDTRY
2719 return ret;
2722 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2723 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2724 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2726 BOOL ret;
2728 __TRY
2730 struct AsnDecodeSequenceItem items[] = {
2731 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2732 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2733 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2734 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2735 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2736 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2737 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2738 AuthorityCertIssuer.rgAltEntry), 0 },
2739 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2740 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2741 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2742 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2743 AuthorityCertSerialNumber.pbData), 0 },
2746 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2747 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2748 pcbStructInfo, NULL, NULL);
2750 __EXCEPT_PAGE_FAULT
2752 SetLastError(STATUS_ACCESS_VIOLATION);
2753 ret = FALSE;
2755 __ENDTRY
2756 return ret;
2759 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
2760 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2761 DWORD *pcbDecoded)
2763 struct AsnDecodeSequenceItem items[] = {
2764 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
2765 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
2766 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
2767 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
2768 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
2769 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
2771 CERT_ACCESS_DESCRIPTION *descr = (CERT_ACCESS_DESCRIPTION *)pvStructInfo;
2773 return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2774 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2775 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
2778 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
2779 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2780 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2782 BOOL ret;
2784 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2785 pDecodePara, pvStructInfo, *pcbStructInfo);
2787 __TRY
2789 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2790 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
2791 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
2793 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2794 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2796 __EXCEPT_PAGE_FAULT
2798 SetLastError(STATUS_ACCESS_VIOLATION);
2799 ret = FALSE;
2801 __ENDTRY
2802 return ret;
2805 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
2806 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2808 BOOL ret;
2809 DWORD dataLen;
2811 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2812 pvStructInfo, *pcbStructInfo, pcbDecoded);
2814 /* The caller has already checked the tag, no need to check it again.
2815 * Check the outer length is valid:
2817 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
2819 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2820 DWORD innerLen;
2822 pbEncoded += 1 + lenBytes;
2823 cbEncoded -= 1 + lenBytes;
2824 if (dataLen == CMSG_INDEFINITE_LENGTH)
2825 cbEncoded -= 2; /* space for 0 TLV */
2826 /* Check the inner length is valid: */
2827 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
2829 DWORD decodedLen;
2831 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
2832 pvStructInfo, pcbStructInfo, &decodedLen);
2833 if (dataLen == CMSG_INDEFINITE_LENGTH)
2835 if (*(pbEncoded + decodedLen) != 0 ||
2836 *(pbEncoded + decodedLen + 1) != 0)
2838 TRACE("expected 0 TLV, got {%02x,%02x}\n",
2839 *(pbEncoded + decodedLen),
2840 *(pbEncoded + decodedLen + 1));
2841 SetLastError(CRYPT_E_ASN1_CORRUPT);
2842 ret = FALSE;
2844 else
2845 decodedLen += 2;
2847 if (ret && pcbDecoded)
2849 *pcbDecoded = 1 + lenBytes + decodedLen;
2850 TRACE("decoded %d bytes\n", *pcbDecoded);
2854 return ret;
2857 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
2858 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2859 DWORD *pcbDecoded)
2861 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2862 struct AsnDecodeSequenceItem items[] = {
2863 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2864 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2865 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2866 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2867 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2868 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2869 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2871 BOOL ret;
2873 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2874 pvStructInfo, *pcbStructInfo, pcbDecoded);
2876 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2877 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2878 pcbDecoded, info ? info->pszObjId : NULL);
2879 return ret;
2882 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2883 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2884 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2886 BOOL ret = FALSE;
2888 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2889 pDecodePara, pvStructInfo, *pcbStructInfo);
2891 __TRY
2893 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
2894 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2895 if (ret && pvStructInfo)
2897 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2898 pcbStructInfo, *pcbStructInfo);
2899 if (ret)
2901 CRYPT_CONTENT_INFO *info;
2903 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2904 pvStructInfo = *(BYTE **)pvStructInfo;
2905 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2906 info->pszObjId = (LPSTR)((BYTE *)info +
2907 sizeof(CRYPT_CONTENT_INFO));
2908 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
2909 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2910 pcbStructInfo, NULL);
2914 __EXCEPT_PAGE_FAULT
2916 SetLastError(STATUS_ACCESS_VIOLATION);
2918 __ENDTRY
2919 return ret;
2922 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2923 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2924 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2926 BOOL ret;
2927 struct AsnDecodeSequenceItem items[] = {
2928 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2929 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2930 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2931 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2932 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2933 0 },
2934 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2935 CRYPT_AsnDecodePKCSContentInfoInternal,
2936 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2937 ContentInfo.pszObjId), 0 },
2938 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2939 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2940 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2943 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2944 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
2945 NULL, NULL);
2946 return ret;
2949 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2950 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2951 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2953 BOOL ret = TRUE;
2955 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2956 pDecodePara, pvStructInfo, *pcbStructInfo);
2958 __TRY
2960 DWORD bytesNeeded;
2962 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2963 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2965 if (!pvStructInfo)
2966 *pcbStructInfo = bytesNeeded;
2967 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2968 pvStructInfo, pcbStructInfo, bytesNeeded)))
2970 CERT_ALT_NAME_INFO *name;
2972 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2973 pvStructInfo = *(BYTE **)pvStructInfo;
2974 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2975 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2976 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2977 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2978 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2979 &bytesNeeded, NULL);
2983 __EXCEPT_PAGE_FAULT
2985 SetLastError(STATUS_ACCESS_VIOLATION);
2986 ret = FALSE;
2988 __ENDTRY
2989 return ret;
2992 struct PATH_LEN_CONSTRAINT
2994 BOOL fPathLenConstraint;
2995 DWORD dwPathLenConstraint;
2998 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
2999 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3000 DWORD *pcbDecoded)
3002 BOOL ret = TRUE;
3003 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3005 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3006 pvStructInfo, *pcbStructInfo, pcbDecoded);
3008 if (!pvStructInfo)
3010 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3011 &size, pcbDecoded);
3012 *pcbStructInfo = bytesNeeded;
3014 else if (*pcbStructInfo < bytesNeeded)
3016 SetLastError(ERROR_MORE_DATA);
3017 *pcbStructInfo = bytesNeeded;
3018 ret = FALSE;
3020 else
3022 struct PATH_LEN_CONSTRAINT *constraint =
3023 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
3025 *pcbStructInfo = bytesNeeded;
3026 size = sizeof(constraint->dwPathLenConstraint);
3027 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3028 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3029 if (ret)
3030 constraint->fPathLenConstraint = TRUE;
3031 TRACE("got an int, dwPathLenConstraint is %d\n",
3032 constraint->dwPathLenConstraint);
3034 TRACE("returning %d (%08x)\n", ret, GetLastError());
3035 return ret;
3038 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3039 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3040 DWORD *pcbDecoded)
3042 BOOL ret;
3043 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3044 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3045 offsetof(CERT_NAME_BLOB, pbData) };
3046 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
3048 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3049 pvStructInfo, *pcbStructInfo, pcbDecoded);
3051 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3052 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3053 entries ? entries->rgItems : NULL);
3054 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3055 return ret;
3058 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3059 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3060 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3062 BOOL ret;
3064 __TRY
3066 struct AsnDecodeSequenceItem items[] = {
3067 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3068 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3069 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3070 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3071 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3072 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3073 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3074 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3075 sizeof(struct GenericArray), TRUE, TRUE,
3076 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3079 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3080 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3081 pcbStructInfo, NULL, NULL);
3083 __EXCEPT_PAGE_FAULT
3085 SetLastError(STATUS_ACCESS_VIOLATION);
3086 ret = FALSE;
3088 __ENDTRY
3089 return ret;
3092 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3093 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3094 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3096 BOOL ret;
3098 __TRY
3100 struct AsnDecodeSequenceItem items[] = {
3101 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3102 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3103 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3104 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3105 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3108 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3109 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3110 pcbStructInfo, NULL, NULL);
3112 __EXCEPT_PAGE_FAULT
3114 SetLastError(STATUS_ACCESS_VIOLATION);
3115 ret = FALSE;
3117 __ENDTRY
3118 return ret;
3121 #define RSA1_MAGIC 0x31415352
3123 struct DECODED_RSA_PUB_KEY
3125 DWORD pubexp;
3126 CRYPT_INTEGER_BLOB modulus;
3129 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3130 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3131 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3133 BOOL ret;
3135 __TRY
3137 struct AsnDecodeSequenceItem items[] = {
3138 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3139 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3140 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3141 0 },
3142 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3143 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3145 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3146 DWORD size = 0;
3148 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3149 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3150 &size, NULL, NULL);
3151 if (ret)
3153 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3154 decodedKey->modulus.cbData;
3156 if (!pvStructInfo)
3158 *pcbStructInfo = bytesNeeded;
3159 ret = TRUE;
3161 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3162 pvStructInfo, pcbStructInfo, bytesNeeded)))
3164 BLOBHEADER *hdr;
3165 RSAPUBKEY *rsaPubKey;
3167 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3168 pvStructInfo = *(BYTE **)pvStructInfo;
3169 hdr = (BLOBHEADER *)pvStructInfo;
3170 hdr->bType = PUBLICKEYBLOB;
3171 hdr->bVersion = CUR_BLOB_VERSION;
3172 hdr->reserved = 0;
3173 hdr->aiKeyAlg = CALG_RSA_KEYX;
3174 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3175 sizeof(BLOBHEADER));
3176 rsaPubKey->magic = RSA1_MAGIC;
3177 rsaPubKey->pubexp = decodedKey->pubexp;
3178 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3179 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3180 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3181 decodedKey->modulus.cbData);
3183 LocalFree(decodedKey);
3186 __EXCEPT_PAGE_FAULT
3188 SetLastError(STATUS_ACCESS_VIOLATION);
3189 ret = FALSE;
3191 __ENDTRY
3192 return ret;
3195 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
3196 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3197 DWORD *pcbDecoded)
3199 BOOL ret;
3200 DWORD bytesNeeded, dataLen;
3202 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3203 pvStructInfo, *pcbStructInfo, pcbDecoded);
3205 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3207 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3209 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3210 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
3211 else
3212 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
3213 if (pcbDecoded)
3214 *pcbDecoded = 1 + lenBytes + dataLen;
3215 if (!pvStructInfo)
3216 *pcbStructInfo = bytesNeeded;
3217 else if (*pcbStructInfo < bytesNeeded)
3219 SetLastError(ERROR_MORE_DATA);
3220 *pcbStructInfo = bytesNeeded;
3221 ret = FALSE;
3223 else
3225 CRYPT_DATA_BLOB *blob;
3227 *pcbStructInfo = bytesNeeded;
3228 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3229 blob->cbData = dataLen;
3230 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3231 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
3232 else
3234 assert(blob->pbData);
3235 if (blob->cbData)
3236 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
3237 blob->cbData);
3241 return ret;
3244 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
3245 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3246 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3248 BOOL ret;
3250 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3251 pDecodePara, pvStructInfo, *pcbStructInfo);
3253 __TRY
3255 DWORD bytesNeeded;
3257 if (!cbEncoded)
3259 SetLastError(CRYPT_E_ASN1_CORRUPT);
3260 ret = FALSE;
3262 else if (pbEncoded[0] != ASN_OCTETSTRING)
3264 SetLastError(CRYPT_E_ASN1_BADTAG);
3265 ret = FALSE;
3267 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3268 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3270 if (!pvStructInfo)
3271 *pcbStructInfo = bytesNeeded;
3272 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3273 pvStructInfo, pcbStructInfo, bytesNeeded)))
3275 CRYPT_DATA_BLOB *blob;
3277 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3278 pvStructInfo = *(BYTE **)pvStructInfo;
3279 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3280 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
3281 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3282 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3283 &bytesNeeded, NULL);
3287 __EXCEPT_PAGE_FAULT
3289 SetLastError(STATUS_ACCESS_VIOLATION);
3290 ret = FALSE;
3292 __ENDTRY
3293 return ret;
3296 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3297 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3299 BOOL ret;
3300 DWORD bytesNeeded, dataLen;
3301 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3303 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3304 pvStructInfo, *pcbStructInfo, pcbDecoded);
3306 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3308 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3309 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3310 else
3311 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3312 if (pcbDecoded)
3313 *pcbDecoded = 1 + lenBytes + dataLen;
3314 if (!pvStructInfo)
3315 *pcbStructInfo = bytesNeeded;
3316 else if (*pcbStructInfo < bytesNeeded)
3318 *pcbStructInfo = bytesNeeded;
3319 SetLastError(ERROR_MORE_DATA);
3320 ret = FALSE;
3322 else
3324 CRYPT_BIT_BLOB *blob;
3326 *pcbStructInfo = bytesNeeded;
3327 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3328 blob->cbData = dataLen - 1;
3329 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3330 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3332 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3334 else
3336 assert(blob->pbData);
3337 if (blob->cbData)
3339 BYTE mask = 0xff << blob->cUnusedBits;
3341 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3342 blob->cbData);
3343 blob->pbData[blob->cbData - 1] &= mask;
3348 return ret;
3351 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3352 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3353 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3355 BOOL ret;
3357 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3358 pDecodePara, pvStructInfo, pcbStructInfo);
3360 __TRY
3362 DWORD bytesNeeded;
3364 if (!cbEncoded)
3366 SetLastError(CRYPT_E_ASN1_CORRUPT);
3367 ret = FALSE;
3369 else if (pbEncoded[0] != ASN_BITSTRING)
3371 SetLastError(CRYPT_E_ASN1_BADTAG);
3372 ret = FALSE;
3374 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3375 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3377 if (!pvStructInfo)
3378 *pcbStructInfo = bytesNeeded;
3379 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3380 pvStructInfo, pcbStructInfo, bytesNeeded)))
3382 CRYPT_BIT_BLOB *blob;
3384 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3385 pvStructInfo = *(BYTE **)pvStructInfo;
3386 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3387 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3388 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3389 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3390 &bytesNeeded, NULL);
3394 __EXCEPT_PAGE_FAULT
3396 SetLastError(STATUS_ACCESS_VIOLATION);
3397 ret = FALSE;
3399 __ENDTRY
3400 TRACE("returning %d (%08x)\n", ret, GetLastError());
3401 return ret;
3404 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
3405 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3406 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3408 BOOL ret;
3409 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3410 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3411 DWORD size = sizeof(buf);
3413 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3414 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, buf,
3415 &size, pcbDecoded);
3416 if (ret)
3418 if (!pvStructInfo)
3419 *pcbStructInfo = sizeof(int);
3420 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3422 int val, i;
3424 if (blob->pbData[blob->cbData - 1] & 0x80)
3426 /* initialize to a negative value to sign-extend */
3427 val = -1;
3429 else
3430 val = 0;
3431 for (i = 0; i < blob->cbData; i++)
3433 val <<= 8;
3434 val |= blob->pbData[blob->cbData - i - 1];
3436 memcpy(pvStructInfo, &val, sizeof(int));
3439 else if (GetLastError() == ERROR_MORE_DATA)
3440 SetLastError(CRYPT_E_ASN1_LARGE);
3441 return ret;
3444 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3445 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3446 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3448 BOOL ret;
3450 __TRY
3452 DWORD bytesNeeded;
3454 if (!cbEncoded)
3456 SetLastError(CRYPT_E_ASN1_EOD);
3457 ret = FALSE;
3459 else if (pbEncoded[0] != ASN_INTEGER)
3461 SetLastError(CRYPT_E_ASN1_BADTAG);
3462 ret = FALSE;
3464 else
3465 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3466 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3467 if (ret)
3469 if (!pvStructInfo)
3470 *pcbStructInfo = bytesNeeded;
3471 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3472 pvStructInfo, pcbStructInfo, bytesNeeded)))
3474 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3475 pvStructInfo = *(BYTE **)pvStructInfo;
3476 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3477 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3478 &bytesNeeded, NULL);
3482 __EXCEPT_PAGE_FAULT
3484 SetLastError(STATUS_ACCESS_VIOLATION);
3485 ret = FALSE;
3487 __ENDTRY
3488 return ret;
3491 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3492 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3493 DWORD *pcbDecoded)
3495 BOOL ret;
3496 DWORD bytesNeeded, dataLen;
3498 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3500 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3502 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3503 if (pcbDecoded)
3504 *pcbDecoded = 1 + lenBytes + dataLen;
3505 if (!pvStructInfo)
3506 *pcbStructInfo = bytesNeeded;
3507 else if (*pcbStructInfo < bytesNeeded)
3509 *pcbStructInfo = bytesNeeded;
3510 SetLastError(ERROR_MORE_DATA);
3511 ret = FALSE;
3513 else
3515 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3517 *pcbStructInfo = bytesNeeded;
3518 blob->cbData = dataLen;
3519 assert(blob->pbData);
3520 if (blob->cbData)
3522 DWORD i;
3524 for (i = 0; i < blob->cbData; i++)
3526 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3527 dataLen - i - 1);
3532 return ret;
3535 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3536 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3537 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3539 BOOL ret;
3541 __TRY
3543 DWORD bytesNeeded;
3545 if (pbEncoded[0] != ASN_INTEGER)
3547 SetLastError(CRYPT_E_ASN1_BADTAG);
3548 ret = FALSE;
3550 else
3551 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3552 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3553 if (ret)
3555 if (!pvStructInfo)
3556 *pcbStructInfo = bytesNeeded;
3557 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3558 pvStructInfo, pcbStructInfo, bytesNeeded)))
3560 CRYPT_INTEGER_BLOB *blob;
3562 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3563 pvStructInfo = *(BYTE **)pvStructInfo;
3564 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3565 blob->pbData = (BYTE *)pvStructInfo +
3566 sizeof(CRYPT_INTEGER_BLOB);
3567 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3568 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3569 &bytesNeeded, NULL);
3573 __EXCEPT_PAGE_FAULT
3575 SetLastError(STATUS_ACCESS_VIOLATION);
3576 ret = FALSE;
3578 __ENDTRY
3579 return ret;
3582 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3583 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3584 DWORD *pcbDecoded)
3586 BOOL ret;
3588 if (pbEncoded[0] == ASN_INTEGER)
3590 DWORD bytesNeeded, dataLen;
3592 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3594 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3596 if (pcbDecoded)
3597 *pcbDecoded = 1 + lenBytes + dataLen;
3598 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3599 if (!pvStructInfo)
3600 *pcbStructInfo = bytesNeeded;
3601 else if (*pcbStructInfo < bytesNeeded)
3603 *pcbStructInfo = bytesNeeded;
3604 SetLastError(ERROR_MORE_DATA);
3605 ret = FALSE;
3607 else
3609 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3611 *pcbStructInfo = bytesNeeded;
3612 blob->cbData = dataLen;
3613 assert(blob->pbData);
3614 /* remove leading zero byte if it exists */
3615 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3617 blob->cbData--;
3618 blob->pbData++;
3620 if (blob->cbData)
3622 DWORD i;
3624 for (i = 0; i < blob->cbData; i++)
3626 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3627 dataLen - i - 1);
3633 else
3635 SetLastError(CRYPT_E_ASN1_BADTAG);
3636 ret = FALSE;
3638 return ret;
3641 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3642 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3643 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3645 BOOL ret;
3647 __TRY
3649 DWORD bytesNeeded;
3651 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
3652 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3654 if (!pvStructInfo)
3655 *pcbStructInfo = bytesNeeded;
3656 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3657 pvStructInfo, pcbStructInfo, bytesNeeded)))
3659 CRYPT_INTEGER_BLOB *blob;
3661 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3662 pvStructInfo = *(BYTE **)pvStructInfo;
3663 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3664 blob->pbData = (BYTE *)pvStructInfo +
3665 sizeof(CRYPT_INTEGER_BLOB);
3666 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
3667 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3668 &bytesNeeded, NULL);
3672 __EXCEPT_PAGE_FAULT
3674 SetLastError(STATUS_ACCESS_VIOLATION);
3675 ret = FALSE;
3677 __ENDTRY
3678 return ret;
3681 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3682 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3683 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3685 BOOL ret;
3687 if (!pvStructInfo)
3689 *pcbStructInfo = sizeof(int);
3690 return TRUE;
3692 __TRY
3694 if (pbEncoded[0] == ASN_ENUMERATED)
3696 unsigned int val = 0, i;
3698 if (cbEncoded <= 1)
3700 SetLastError(CRYPT_E_ASN1_EOD);
3701 ret = FALSE;
3703 else if (pbEncoded[1] == 0)
3705 SetLastError(CRYPT_E_ASN1_CORRUPT);
3706 ret = FALSE;
3708 else
3710 /* A little strange looking, but we have to accept a sign byte:
3711 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3712 * assuming a small length is okay here, it has to be in short
3713 * form.
3715 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3717 SetLastError(CRYPT_E_ASN1_LARGE);
3718 return FALSE;
3720 for (i = 0; i < pbEncoded[1]; i++)
3722 val <<= 8;
3723 val |= pbEncoded[2 + i];
3725 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3726 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3728 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3729 pvStructInfo = *(BYTE **)pvStructInfo;
3730 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3734 else
3736 SetLastError(CRYPT_E_ASN1_BADTAG);
3737 ret = FALSE;
3740 __EXCEPT_PAGE_FAULT
3742 SetLastError(STATUS_ACCESS_VIOLATION);
3743 ret = FALSE;
3745 __ENDTRY
3746 return ret;
3749 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3750 * if it fails.
3752 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3753 do { \
3754 BYTE i; \
3756 (word) = 0; \
3757 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3759 if (!isdigit(*(pbEncoded))) \
3761 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3762 ret = FALSE; \
3764 else \
3766 (word) *= 10; \
3767 (word) += *(pbEncoded)++ - '0'; \
3770 } while (0)
3772 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3773 SYSTEMTIME *sysTime)
3775 BOOL ret = TRUE;
3777 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3779 WORD hours, minutes = 0;
3780 BYTE sign = *pbEncoded++;
3782 len--;
3783 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3784 if (ret && hours >= 24)
3786 SetLastError(CRYPT_E_ASN1_CORRUPT);
3787 ret = FALSE;
3789 else if (len >= 2)
3791 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3792 if (ret && minutes >= 60)
3794 SetLastError(CRYPT_E_ASN1_CORRUPT);
3795 ret = FALSE;
3798 if (ret)
3800 if (sign == '+')
3802 sysTime->wHour += hours;
3803 sysTime->wMinute += minutes;
3805 else
3807 if (hours > sysTime->wHour)
3809 sysTime->wDay--;
3810 sysTime->wHour = 24 - (hours - sysTime->wHour);
3812 else
3813 sysTime->wHour -= hours;
3814 if (minutes > sysTime->wMinute)
3816 sysTime->wHour--;
3817 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3819 else
3820 sysTime->wMinute -= minutes;
3824 return ret;
3827 #define MIN_ENCODED_TIME_LENGTH 10
3829 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3830 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3831 DWORD *pcbDecoded)
3833 BOOL ret = FALSE;
3835 if (pbEncoded[0] == ASN_UTCTIME)
3837 if (cbEncoded <= 1)
3838 SetLastError(CRYPT_E_ASN1_EOD);
3839 else if (pbEncoded[1] > 0x7f)
3841 /* long-form date strings really can't be valid */
3842 SetLastError(CRYPT_E_ASN1_CORRUPT);
3844 else
3846 SYSTEMTIME sysTime = { 0 };
3847 BYTE len = pbEncoded[1];
3849 if (len < MIN_ENCODED_TIME_LENGTH)
3850 SetLastError(CRYPT_E_ASN1_CORRUPT);
3851 else
3853 ret = TRUE;
3854 if (pcbDecoded)
3855 *pcbDecoded = 2 + len;
3856 pbEncoded += 2;
3857 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3858 if (sysTime.wYear >= 50)
3859 sysTime.wYear += 1900;
3860 else
3861 sysTime.wYear += 2000;
3862 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3863 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3864 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3865 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3866 if (ret && len > 0)
3868 if (len >= 2 && isdigit(*pbEncoded) &&
3869 isdigit(*(pbEncoded + 1)))
3870 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3871 sysTime.wSecond);
3872 else if (isdigit(*pbEncoded))
3873 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3874 sysTime.wSecond);
3875 if (ret)
3876 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3877 &sysTime);
3879 if (ret)
3881 if (!pvStructInfo)
3882 *pcbStructInfo = sizeof(FILETIME);
3883 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3884 sizeof(FILETIME))))
3885 ret = SystemTimeToFileTime(&sysTime,
3886 (FILETIME *)pvStructInfo);
3891 else
3892 SetLastError(CRYPT_E_ASN1_BADTAG);
3893 return ret;
3896 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3897 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3898 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3900 BOOL ret = FALSE;
3902 __TRY
3904 DWORD bytesNeeded;
3906 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3907 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3908 if (ret)
3910 if (!pvStructInfo)
3911 *pcbStructInfo = bytesNeeded;
3912 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3913 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3915 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3916 pvStructInfo = *(BYTE **)pvStructInfo;
3917 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3918 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3919 &bytesNeeded, NULL);
3923 __EXCEPT_PAGE_FAULT
3925 SetLastError(STATUS_ACCESS_VIOLATION);
3927 __ENDTRY
3928 return ret;
3931 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3932 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3933 DWORD *pcbDecoded)
3935 BOOL ret = FALSE;
3937 if (pbEncoded[0] == ASN_GENERALTIME)
3939 if (cbEncoded <= 1)
3940 SetLastError(CRYPT_E_ASN1_EOD);
3941 else if (pbEncoded[1] > 0x7f)
3943 /* long-form date strings really can't be valid */
3944 SetLastError(CRYPT_E_ASN1_CORRUPT);
3946 else
3948 BYTE len = pbEncoded[1];
3950 if (len < MIN_ENCODED_TIME_LENGTH)
3951 SetLastError(CRYPT_E_ASN1_CORRUPT);
3952 else
3954 SYSTEMTIME sysTime = { 0 };
3956 ret = TRUE;
3957 if (pcbDecoded)
3958 *pcbDecoded = 2 + len;
3959 pbEncoded += 2;
3960 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3961 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3962 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3963 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3964 if (ret && len > 0)
3966 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3967 sysTime.wMinute);
3968 if (ret && len > 0)
3969 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3970 sysTime.wSecond);
3971 if (ret && len > 0 && (*pbEncoded == '.' ||
3972 *pbEncoded == ','))
3974 BYTE digits;
3976 pbEncoded++;
3977 len--;
3978 /* workaround macro weirdness */
3979 digits = min(len, 3);
3980 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3981 sysTime.wMilliseconds);
3983 if (ret)
3984 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3985 &sysTime);
3987 if (ret)
3989 if (!pvStructInfo)
3990 *pcbStructInfo = sizeof(FILETIME);
3991 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3992 sizeof(FILETIME))))
3993 ret = SystemTimeToFileTime(&sysTime,
3994 (FILETIME *)pvStructInfo);
3999 else
4000 SetLastError(CRYPT_E_ASN1_BADTAG);
4001 return ret;
4004 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4005 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4006 DWORD *pcbDecoded)
4008 BOOL ret;
4009 InternalDecodeFunc decode = NULL;
4011 if (pbEncoded[0] == ASN_UTCTIME)
4012 decode = CRYPT_AsnDecodeUtcTimeInternal;
4013 else if (pbEncoded[0] == ASN_GENERALTIME)
4014 decode = CRYPT_AsnDecodeGeneralizedTime;
4015 if (decode)
4016 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
4017 pcbStructInfo, pcbDecoded);
4018 else
4020 SetLastError(CRYPT_E_ASN1_BADTAG);
4021 ret = FALSE;
4023 return ret;
4026 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
4027 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4028 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4030 BOOL ret;
4032 __TRY
4034 DWORD bytesNeeded;
4036 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4037 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4038 if (ret)
4040 if (!pvStructInfo)
4041 *pcbStructInfo = bytesNeeded;
4042 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4043 pvStructInfo, pcbStructInfo, bytesNeeded)))
4045 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4046 pvStructInfo = *(BYTE **)pvStructInfo;
4047 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4048 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4049 &bytesNeeded, NULL);
4053 __EXCEPT_PAGE_FAULT
4055 SetLastError(STATUS_ACCESS_VIOLATION);
4056 ret = FALSE;
4058 __ENDTRY
4059 return ret;
4062 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
4063 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4064 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4066 BOOL ret = TRUE;
4068 __TRY
4070 if (pbEncoded[0] == ASN_SEQUENCEOF)
4072 DWORD bytesNeeded, dataLen, remainingLen, cValue;
4074 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4076 BYTE lenBytes;
4077 const BYTE *ptr;
4079 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4080 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
4081 cValue = 0;
4082 ptr = pbEncoded + 1 + lenBytes;
4083 remainingLen = dataLen;
4084 while (ret && remainingLen)
4086 DWORD nextLen;
4088 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4089 if (ret)
4091 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4093 remainingLen -= 1 + nextLenBytes + nextLen;
4094 ptr += 1 + nextLenBytes + nextLen;
4095 bytesNeeded += sizeof(CRYPT_DER_BLOB);
4096 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
4097 bytesNeeded += 1 + nextLenBytes + nextLen;
4098 cValue++;
4101 if (ret)
4103 CRYPT_SEQUENCE_OF_ANY *seq;
4104 BYTE *nextPtr;
4105 DWORD i;
4107 if (!pvStructInfo)
4108 *pcbStructInfo = bytesNeeded;
4109 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4110 pvStructInfo, pcbStructInfo, bytesNeeded)))
4112 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4113 pvStructInfo = *(BYTE **)pvStructInfo;
4114 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
4115 seq->cValue = cValue;
4116 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
4117 sizeof(*seq));
4118 nextPtr = (BYTE *)seq->rgValue +
4119 cValue * sizeof(CRYPT_DER_BLOB);
4120 ptr = pbEncoded + 1 + lenBytes;
4121 remainingLen = dataLen;
4122 i = 0;
4123 while (ret && remainingLen)
4125 DWORD nextLen;
4127 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4128 if (ret)
4130 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4132 seq->rgValue[i].cbData = 1 + nextLenBytes +
4133 nextLen;
4134 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4135 seq->rgValue[i].pbData = (BYTE *)ptr;
4136 else
4138 seq->rgValue[i].pbData = nextPtr;
4139 memcpy(nextPtr, ptr, 1 + nextLenBytes +
4140 nextLen);
4141 nextPtr += 1 + nextLenBytes + nextLen;
4143 remainingLen -= 1 + nextLenBytes + nextLen;
4144 ptr += 1 + nextLenBytes + nextLen;
4145 i++;
4152 else
4154 SetLastError(CRYPT_E_ASN1_BADTAG);
4155 ret = FALSE;
4158 __EXCEPT_PAGE_FAULT
4160 SetLastError(STATUS_ACCESS_VIOLATION);
4161 ret = FALSE;
4163 __ENDTRY
4164 return ret;
4167 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4168 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4169 DWORD *pcbDecoded)
4171 BOOL ret;
4173 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
4175 DWORD bytesNeeded, dataLen;
4177 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4179 struct AsnArrayDescriptor arrayDesc = {
4180 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
4181 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
4182 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
4183 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4184 DWORD nameLen;
4186 if (dataLen)
4188 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4189 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4190 0, NULL, NULL, &nameLen, NULL, NULL);
4191 /* The CERT_ALT_NAME_INFO's size is included by CRYPT_AsnDecodeArray
4192 * as the sizeof(struct GenericArray), so don't include it in the
4193 * total bytes needed.
4195 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
4196 sizeof(CERT_ALT_NAME_INFO);
4198 else
4199 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
4200 if (pcbDecoded)
4201 *pcbDecoded = 1 + lenBytes + dataLen;
4202 if (!pvStructInfo)
4203 *pcbStructInfo = bytesNeeded;
4204 else if (*pcbStructInfo < bytesNeeded)
4206 *pcbStructInfo = bytesNeeded;
4207 SetLastError(ERROR_MORE_DATA);
4208 ret = FALSE;
4210 else
4212 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
4214 *pcbStructInfo = bytesNeeded;
4215 if (dataLen)
4217 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
4218 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4219 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4220 0, NULL, &name->u.FullName, &nameLen, NULL,
4221 name->u.FullName.rgAltEntry);
4223 else
4224 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
4228 else
4230 SetLastError(CRYPT_E_ASN1_BADTAG);
4231 ret = FALSE;
4233 return ret;
4236 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
4237 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4239 struct AsnDecodeSequenceItem items[] = {
4240 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
4241 DistPointName), CRYPT_AsnDecodeDistPointName,
4242 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
4243 DistPointName.u.FullName.rgAltEntry), 0 },
4244 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
4245 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
4246 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
4247 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
4248 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
4249 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
4251 BOOL ret;
4253 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4254 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4255 pcbDecoded, NULL);
4256 return ret;
4259 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
4260 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4261 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4263 BOOL ret;
4265 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4266 pDecodePara, pvStructInfo, *pcbStructInfo);
4268 __TRY
4270 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4271 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
4272 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
4274 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4275 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4277 __EXCEPT_PAGE_FAULT
4279 SetLastError(STATUS_ACCESS_VIOLATION);
4280 ret = FALSE;
4282 __ENDTRY
4283 return ret;
4286 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
4287 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4288 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4290 BOOL ret;
4292 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4293 pDecodePara, pvStructInfo, *pcbStructInfo);
4295 __TRY
4297 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4298 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4300 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4301 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4303 __EXCEPT_PAGE_FAULT
4305 SetLastError(STATUS_ACCESS_VIOLATION);
4306 ret = FALSE;
4308 __ENDTRY
4309 return ret;
4312 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4313 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4314 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4316 BOOL ret;
4318 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4319 pDecodePara, pvStructInfo, *pcbStructInfo);
4321 __TRY
4323 struct AsnDecodeSequenceItem items[] = {
4324 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4325 DistPointName), CRYPT_AsnDecodeDistPointName,
4326 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4327 offsetof(CRL_ISSUING_DIST_POINT,
4328 DistPointName.u.FullName.rgAltEntry), 0 },
4329 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4330 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4331 FALSE, 0 },
4332 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4333 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4334 FALSE, 0 },
4335 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4336 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4337 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4338 OnlySomeReasonFlags.pbData), 0 },
4339 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4340 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4343 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4344 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4345 pcbStructInfo, NULL, NULL);
4347 __EXCEPT_PAGE_FAULT
4349 SetLastError(STATUS_ACCESS_VIOLATION);
4350 ret = FALSE;
4352 __ENDTRY
4353 return ret;
4356 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
4357 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4358 DWORD *pcbDecoded)
4360 BOOL ret = FALSE;
4362 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4363 pvStructInfo, *pcbStructInfo, pcbDecoded);
4365 if (!cbEncoded)
4367 SetLastError(CRYPT_E_ASN1_EOD);
4368 return FALSE;
4370 if (pbEncoded[0] != (ASN_CONTEXT | 1))
4372 SetLastError(CRYPT_E_ASN1_BADTAG);
4373 return FALSE;
4375 /* The BOOL is implicit: if the integer is present, then it's TRUE */
4376 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
4377 pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo,
4378 pcbDecoded);
4379 if (ret && pvStructInfo)
4380 *(BOOL *)pvStructInfo = TRUE;
4381 TRACE("returning %d\n", ret);
4382 return ret;
4385 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
4386 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4387 DWORD *pcbDecoded)
4389 BOOL ret;
4390 struct AsnDecodeSequenceItem items[] = {
4391 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
4392 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
4393 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
4394 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
4395 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
4396 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
4397 CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0,
4398 0 },
4400 CERT_GENERAL_SUBTREE *subtree = (CERT_GENERAL_SUBTREE *)pvStructInfo;
4402 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4403 pvStructInfo, *pcbStructInfo, pcbDecoded);
4405 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4406 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4407 pcbDecoded, subtree ? (BYTE *)subtree->Base.u.pwszURL : NULL);
4408 if (pcbDecoded)
4410 TRACE("%d\n", *pcbDecoded);
4411 if (*pcbDecoded < cbEncoded)
4412 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
4413 *(pbEncoded + *pcbDecoded + 1));
4415 TRACE("returning %d\n", ret);
4416 return ret;
4419 static BOOL CRYPT_AsnDecodeSubtreeArray(const BYTE *pbEncoded,
4420 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4421 DWORD *pcbDecoded)
4423 BOOL ret = TRUE;
4424 struct AsnArrayDescriptor arrayDesc = { 0,
4425 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4426 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4427 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4429 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4430 pvStructInfo, *pcbStructInfo, pcbDecoded);
4432 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4433 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4434 array ? array->rgItems : NULL);
4435 return ret;
4439 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
4440 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4441 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4443 BOOL ret = FALSE;
4445 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4446 pDecodePara, pvStructInfo, *pcbStructInfo);
4448 __TRY
4450 struct AsnDecodeSequenceItem items[] = {
4451 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4452 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
4453 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4454 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
4455 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
4456 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4457 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4458 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
4461 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4462 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4463 pcbStructInfo, NULL, NULL);
4465 __EXCEPT_PAGE_FAULT
4467 SetLastError(STATUS_ACCESS_VIOLATION);
4469 __ENDTRY
4470 return ret;
4473 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
4474 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4475 DWORD *pcbDecoded)
4477 BOOL ret;
4478 struct AsnDecodeSequenceItem items[] = {
4479 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4480 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4481 Issuer.pbData) },
4482 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4483 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4484 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4486 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4487 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4489 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4490 pvStructInfo, *pcbStructInfo, pcbDecoded);
4492 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4493 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4494 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4495 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4497 SetLastError(CRYPT_E_ASN1_CORRUPT);
4498 ret = FALSE;
4500 TRACE("returning %d\n", ret);
4501 return ret;
4504 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4505 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4506 DWORD *pcbDecoded)
4508 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4509 struct AsnDecodeSequenceItem items[] = {
4510 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4511 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4512 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4513 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4514 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4515 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4516 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4517 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4518 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4519 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4520 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4521 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4522 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4523 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4524 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4525 HashEncryptionAlgorithm.pszObjId), 0 },
4526 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4527 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4528 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4529 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4530 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4531 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4532 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4534 BOOL ret;
4536 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4537 pvStructInfo, *pcbStructInfo);
4539 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4540 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4541 pcbDecoded, info ? info->Issuer.pbData : NULL);
4542 return ret;
4545 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4546 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4547 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4549 BOOL ret = FALSE;
4551 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4552 pDecodePara, pvStructInfo, *pcbStructInfo);
4554 __TRY
4556 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4557 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4558 if (ret && pvStructInfo)
4560 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4561 pcbStructInfo, *pcbStructInfo);
4562 if (ret)
4564 CMSG_SIGNER_INFO *info;
4566 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4567 pvStructInfo = *(BYTE **)pvStructInfo;
4568 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4569 info->Issuer.pbData = ((BYTE *)info +
4570 sizeof(CMSG_SIGNER_INFO));
4571 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4572 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4573 pcbStructInfo, NULL);
4577 __EXCEPT_PAGE_FAULT
4579 SetLastError(STATUS_ACCESS_VIOLATION);
4581 __ENDTRY
4582 TRACE("returning %d\n", ret);
4583 return ret;
4586 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
4587 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4588 DWORD *pcbDecoded)
4590 CERT_ID *id = (CERT_ID *)pvStructInfo;
4591 BOOL ret = FALSE;
4593 if (*pbEncoded == ASN_SEQUENCEOF)
4595 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
4596 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
4597 if (ret)
4599 if (id)
4600 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
4601 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
4602 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4603 sizeof(CERT_ISSUER_SERIAL_NUMBER);
4604 else
4605 *pcbStructInfo = sizeof(CERT_ID);
4608 else if (*pbEncoded == (ASN_CONTEXT | 0))
4610 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
4611 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
4612 if (ret)
4614 if (id)
4615 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
4616 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
4617 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4618 sizeof(CRYPT_DATA_BLOB);
4619 else
4620 *pcbStructInfo = sizeof(CERT_ID);
4623 else
4624 SetLastError(CRYPT_E_ASN1_BADTAG);
4625 return ret;
4628 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
4629 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4630 DWORD *pcbDecoded)
4632 CMSG_CMS_SIGNER_INFO *info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4633 struct AsnDecodeSequenceItem items[] = {
4634 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
4635 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4636 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
4637 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
4638 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
4639 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
4640 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4641 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4642 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4643 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
4644 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4645 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4646 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
4647 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4648 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
4649 HashEncryptionAlgorithm.pszObjId), 0 },
4650 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
4651 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4652 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
4653 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4654 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
4655 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4656 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4658 BOOL ret;
4660 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4661 pvStructInfo, *pcbStructInfo);
4663 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4664 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4665 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
4666 return ret;
4669 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
4670 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4671 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4673 BOOL ret = FALSE;
4675 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4676 pDecodePara, pvStructInfo, *pcbStructInfo);
4678 __TRY
4680 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
4681 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4682 if (ret && pvStructInfo)
4684 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4685 pcbStructInfo, *pcbStructInfo);
4686 if (ret)
4688 CMSG_CMS_SIGNER_INFO *info;
4690 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4691 pvStructInfo = *(BYTE **)pvStructInfo;
4692 info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4693 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
4694 sizeof(CMSG_CMS_SIGNER_INFO));
4695 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
4696 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4697 pcbStructInfo, NULL);
4701 __EXCEPT_PAGE_FAULT
4703 SetLastError(STATUS_ACCESS_VIOLATION);
4705 __ENDTRY
4706 TRACE("returning %d\n", ret);
4707 return ret;
4710 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
4711 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4713 BOOL ret;
4714 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4715 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
4716 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
4717 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4719 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4720 pvStructInfo, *pcbStructInfo, pcbDecoded);
4722 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4723 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4724 array ? array->rgItems : NULL);
4725 return ret;
4728 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4729 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4730 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4732 BOOL ret = FALSE;
4733 struct AsnDecodeSequenceItem items[] = {
4734 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4735 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4736 /* Placeholder for the hash algorithms - redundant with those in the
4737 * signers, so just ignore them.
4739 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4740 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4741 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4742 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4743 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4744 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4745 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4746 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4747 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4748 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4749 sizeof(struct GenericArray), TRUE, TRUE,
4750 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4751 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4752 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4753 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4756 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4757 pDecodePara, signedInfo, *pcbSignedInfo);
4759 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4760 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
4761 NULL, NULL);
4762 TRACE("returning %d\n", ret);
4763 return ret;
4766 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4767 LPCSTR lpszStructType)
4769 CryptDecodeObjectExFunc decodeFunc = NULL;
4771 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4772 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4774 SetLastError(ERROR_FILE_NOT_FOUND);
4775 return NULL;
4777 if (!HIWORD(lpszStructType))
4779 switch (LOWORD(lpszStructType))
4781 case LOWORD(X509_CERT):
4782 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4783 break;
4784 case LOWORD(X509_CERT_TO_BE_SIGNED):
4785 decodeFunc = CRYPT_AsnDecodeCert;
4786 break;
4787 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4788 decodeFunc = CRYPT_AsnDecodeCRL;
4789 break;
4790 case LOWORD(X509_EXTENSIONS):
4791 decodeFunc = CRYPT_AsnDecodeExtensions;
4792 break;
4793 case LOWORD(X509_NAME_VALUE):
4794 decodeFunc = CRYPT_AsnDecodeNameValue;
4795 break;
4796 case LOWORD(X509_NAME):
4797 decodeFunc = CRYPT_AsnDecodeName;
4798 break;
4799 case LOWORD(X509_PUBLIC_KEY_INFO):
4800 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4801 break;
4802 case LOWORD(X509_AUTHORITY_KEY_ID):
4803 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4804 break;
4805 case LOWORD(X509_ALTERNATE_NAME):
4806 decodeFunc = CRYPT_AsnDecodeAltName;
4807 break;
4808 case LOWORD(X509_BASIC_CONSTRAINTS):
4809 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4810 break;
4811 case LOWORD(X509_BASIC_CONSTRAINTS2):
4812 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4813 break;
4814 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4815 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4816 break;
4817 case LOWORD(X509_UNICODE_NAME):
4818 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4819 break;
4820 case LOWORD(PKCS_ATTRIBUTE):
4821 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4822 break;
4823 case LOWORD(X509_UNICODE_NAME_VALUE):
4824 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4825 break;
4826 case LOWORD(X509_OCTET_STRING):
4827 decodeFunc = CRYPT_AsnDecodeOctets;
4828 break;
4829 case LOWORD(X509_BITS):
4830 case LOWORD(X509_KEY_USAGE):
4831 decodeFunc = CRYPT_AsnDecodeBits;
4832 break;
4833 case LOWORD(X509_INTEGER):
4834 decodeFunc = CRYPT_AsnDecodeInt;
4835 break;
4836 case LOWORD(X509_MULTI_BYTE_INTEGER):
4837 decodeFunc = CRYPT_AsnDecodeInteger;
4838 break;
4839 case LOWORD(X509_MULTI_BYTE_UINT):
4840 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4841 break;
4842 case LOWORD(X509_ENUMERATED):
4843 decodeFunc = CRYPT_AsnDecodeEnumerated;
4844 break;
4845 case LOWORD(X509_CHOICE_OF_TIME):
4846 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4847 break;
4848 case LOWORD(X509_AUTHORITY_KEY_ID2):
4849 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4850 break;
4851 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
4852 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
4853 break;
4854 case LOWORD(PKCS_CONTENT_INFO):
4855 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4856 break;
4857 case LOWORD(X509_SEQUENCE_OF_ANY):
4858 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4859 break;
4860 case LOWORD(PKCS_UTC_TIME):
4861 decodeFunc = CRYPT_AsnDecodeUtcTime;
4862 break;
4863 case LOWORD(X509_CRL_DIST_POINTS):
4864 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4865 break;
4866 case LOWORD(X509_ENHANCED_KEY_USAGE):
4867 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4868 break;
4869 case LOWORD(PKCS_CTL):
4870 decodeFunc = CRYPT_AsnDecodeCTL;
4871 break;
4872 case LOWORD(PKCS_SMIME_CAPABILITIES):
4873 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
4874 break;
4875 case LOWORD(PKCS_ATTRIBUTES):
4876 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4877 break;
4878 case LOWORD(X509_ISSUING_DIST_POINT):
4879 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4880 break;
4881 case LOWORD(X509_NAME_CONSTRAINTS):
4882 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4883 break;
4884 case LOWORD(PKCS7_SIGNER_INFO):
4885 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4886 break;
4887 case LOWORD(CMS_SIGNER_INFO):
4888 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
4889 break;
4892 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4893 decodeFunc = CRYPT_AsnDecodeExtensions;
4894 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4895 decodeFunc = CRYPT_AsnDecodeUtcTime;
4896 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4897 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
4898 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4899 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4900 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4901 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4902 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4903 decodeFunc = CRYPT_AsnDecodeEnumerated;
4904 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4905 decodeFunc = CRYPT_AsnDecodeBits;
4906 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4907 decodeFunc = CRYPT_AsnDecodeOctets;
4908 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4909 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4910 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4911 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4912 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4913 decodeFunc = CRYPT_AsnDecodeAltName;
4914 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4915 decodeFunc = CRYPT_AsnDecodeAltName;
4916 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4917 decodeFunc = CRYPT_AsnDecodeAltName;
4918 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4919 decodeFunc = CRYPT_AsnDecodeAltName;
4920 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4921 decodeFunc = CRYPT_AsnDecodeAltName;
4922 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4923 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4924 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4925 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4926 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4927 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4928 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4929 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4930 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
4931 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
4932 else if (!strcmp(lpszStructType, szOID_CTL))
4933 decodeFunc = CRYPT_AsnDecodeCTL;
4934 return decodeFunc;
4937 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4938 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4940 static HCRYPTOIDFUNCSET set = NULL;
4941 CryptDecodeObjectFunc decodeFunc = NULL;
4943 if (!set)
4944 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4945 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4946 (void **)&decodeFunc, hFunc);
4947 return decodeFunc;
4950 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4951 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4953 static HCRYPTOIDFUNCSET set = NULL;
4954 CryptDecodeObjectExFunc decodeFunc = NULL;
4956 if (!set)
4957 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4958 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4959 (void **)&decodeFunc, hFunc);
4960 return decodeFunc;
4963 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4964 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4965 DWORD *pcbStructInfo)
4967 BOOL ret = FALSE;
4968 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4969 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4970 HCRYPTOIDFUNCADDR hFunc = NULL;
4972 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4973 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4974 pvStructInfo, pcbStructInfo);
4976 if (!pvStructInfo && !pcbStructInfo)
4978 SetLastError(ERROR_INVALID_PARAMETER);
4979 return FALSE;
4981 if (cbEncoded > MAX_ENCODED_LEN)
4983 SetLastError(CRYPT_E_ASN1_LARGE);
4984 return FALSE;
4987 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4988 lpszStructType)))
4990 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4991 debugstr_a(lpszStructType));
4992 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4993 lpszStructType, &hFunc);
4994 if (!pCryptDecodeObject)
4995 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4996 lpszStructType, &hFunc);
4998 if (pCryptDecodeObject)
4999 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5000 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5001 else if (pCryptDecodeObjectEx)
5002 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
5003 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
5004 pvStructInfo, pcbStructInfo);
5005 if (hFunc)
5006 CryptFreeOIDFunctionAddress(hFunc, 0);
5007 TRACE_(crypt)("returning %d\n", ret);
5008 return ret;
5011 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5012 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5013 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5015 BOOL ret = FALSE;
5016 CryptDecodeObjectExFunc decodeFunc;
5017 HCRYPTOIDFUNCADDR hFunc = NULL;
5019 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
5020 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5021 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5023 if (!pvStructInfo && !pcbStructInfo)
5025 SetLastError(ERROR_INVALID_PARAMETER);
5026 return FALSE;
5028 if (cbEncoded > MAX_ENCODED_LEN)
5030 SetLastError(CRYPT_E_ASN1_LARGE);
5031 return FALSE;
5034 SetLastError(NOERROR);
5035 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5036 *(BYTE **)pvStructInfo = NULL;
5037 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
5038 if (!decodeFunc)
5040 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5041 debugstr_a(lpszStructType));
5042 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
5043 &hFunc);
5045 if (decodeFunc)
5046 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5047 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5048 else
5050 CryptDecodeObjectFunc pCryptDecodeObject =
5051 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
5053 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
5054 * directly, as that could cause an infinite loop.
5056 if (pCryptDecodeObject)
5058 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5060 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5061 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
5062 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5063 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
5064 ret = pCryptDecodeObject(dwCertEncodingType,
5065 lpszStructType, pbEncoded, cbEncoded, dwFlags,
5066 *(BYTE **)pvStructInfo, pcbStructInfo);
5068 else
5069 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5070 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5073 if (hFunc)
5074 CryptFreeOIDFunctionAddress(hFunc, 0);
5075 TRACE_(crypt)("returning %d\n", ret);
5076 return ret;