d3d8: Stop setting the device state in d3d8_device_SetPixelShaderConstant().
[wine.git] / dlls / crypt32 / decode.c
blobaa697e3bfa8c73d59c4e0a771388d14cc666dfec
1 /*
2 * Copyright 2005-2009 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 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
62 DWORD, DWORD, void *, DWORD *);
63 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
64 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
66 /* Internal decoders don't do memory allocation or exception handling, and
67 * they report how many bytes they decoded.
69 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
70 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
72 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
73 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
74 DWORD *pcbDecoded);
75 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
76 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
77 DWORD *pcbDecoded);
78 /* Assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set ahead of time.
80 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
81 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
82 /* Assumes algo->Parameters.pbData is set ahead of time. */
83 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
84 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
85 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
86 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
87 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
88 static BOOL CRYPT_AsnDecodeOctets(const BYTE *pbEncoded,
89 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
90 DWORD *pcbDecoded);
91 /* Doesn't check the tag, assumes the caller does so */
92 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
93 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
94 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
95 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
96 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
97 * member has been initialized, doesn't do exception handling, and doesn't do
98 * memory allocation. Also doesn't check tag, assumes the caller has checked
99 * it.
101 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
102 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
103 DWORD *pcbDecoded);
104 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
105 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
106 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
107 DWORD *pcbDecoded);
108 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
109 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
110 DWORD *pcbDecoded);
112 /* Gets the number of length bytes from the given (leading) length byte */
113 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
115 /* Helper function to get the encoded length of the data starting at pbEncoded,
116 * where pbEncoded[0] is the tag. If the data are too short to contain a
117 * length or if the length is too large for cbEncoded, sets an appropriate
118 * error code and returns FALSE. If the encoded length is unknown due to
119 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
121 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
122 DWORD *len)
124 BOOL ret;
126 if (cbEncoded <= 1)
128 SetLastError(CRYPT_E_ASN1_CORRUPT);
129 ret = FALSE;
131 else if (pbEncoded[1] <= 0x7f)
133 if (pbEncoded[1] + 1 > cbEncoded)
135 SetLastError(CRYPT_E_ASN1_EOD);
136 ret = FALSE;
138 else
140 *len = pbEncoded[1];
141 ret = TRUE;
144 else if (pbEncoded[1] == 0x80)
146 *len = CMSG_INDEFINITE_LENGTH;
147 ret = TRUE;
149 else
151 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
153 if (lenLen > sizeof(DWORD) + 1)
155 SetLastError(CRYPT_E_ASN1_LARGE);
156 ret = FALSE;
158 else if (lenLen + 2 > cbEncoded)
160 SetLastError(CRYPT_E_ASN1_CORRUPT);
161 ret = FALSE;
163 else
165 DWORD out = 0;
167 pbEncoded += 2;
168 while (--lenLen)
170 out <<= 8;
171 out |= *pbEncoded++;
173 if (out + lenLen + 1 > cbEncoded)
175 SetLastError(CRYPT_E_ASN1_EOD);
176 ret = FALSE;
178 else
180 *len = out;
181 ret = TRUE;
185 return ret;
188 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
189 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
191 BOOL ret;
193 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
194 *len == CMSG_INDEFINITE_LENGTH)
196 SetLastError(CRYPT_E_ASN1_CORRUPT);
197 ret = FALSE;
199 return ret;
202 /* Helper function to check *pcbStructInfo, set it to the required size, and
203 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
204 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
205 * pointer to the newly allocated memory.
207 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
208 const CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
209 DWORD bytesNeeded)
211 BOOL ret = TRUE;
213 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
215 if (pDecodePara && pDecodePara->pfnAlloc)
216 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
217 else
218 *(BYTE **)pvStructInfo = LocalAlloc(LPTR, bytesNeeded);
219 if (!*(BYTE **)pvStructInfo)
220 ret = FALSE;
221 else
222 *pcbStructInfo = bytesNeeded;
224 else if (*pcbStructInfo < bytesNeeded)
226 *pcbStructInfo = bytesNeeded;
227 SetLastError(ERROR_MORE_DATA);
228 ret = FALSE;
230 else
231 *pcbStructInfo = bytesNeeded;
232 return ret;
235 static void CRYPT_FreeSpace(const CRYPT_DECODE_PARA *pDecodePara, LPVOID pv)
237 if (pDecodePara && pDecodePara->pfnFree)
238 pDecodePara->pfnFree(pv);
239 else
240 LocalFree(pv);
243 /* Helper function to check *pcbStructInfo and set it to the required size.
244 * Assumes pvStructInfo is not NULL.
246 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
248 BOOL ret;
250 if (*pcbStructInfo < bytesNeeded)
252 *pcbStructInfo = bytesNeeded;
253 SetLastError(ERROR_MORE_DATA);
254 ret = FALSE;
256 else
258 *pcbStructInfo = bytesNeeded;
259 ret = TRUE;
261 return ret;
264 /* tag:
265 * The expected tag of the item. If tag is 0, decodeFunc is called
266 * regardless of the tag value seen.
267 * offset:
268 * A sequence is decoded into a struct. The offset member is the
269 * offset of this item within that struct.
270 * decodeFunc:
271 * The decoder function to use. If this is NULL, then the member isn't
272 * decoded, but minSize space is reserved for it.
273 * minSize:
274 * The minimum amount of space occupied after decoding. You must set this.
275 * optional:
276 * If true, and the tag doesn't match the expected tag for this item,
277 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
278 * filled with 0 for this member.
279 * hasPointer, pointerOffset:
280 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
281 * the offset within the struct of the data pointer (or to the
282 * first data pointer, if more than one exist).
283 * size:
284 * Used by CRYPT_AsnDecodeSequence, not for your use.
286 struct AsnDecodeSequenceItem
288 BYTE tag;
289 DWORD offset;
290 InternalDecodeFunc decodeFunc;
291 DWORD minSize;
292 BOOL optional;
293 BOOL hasPointer;
294 DWORD pointerOffset;
295 DWORD size;
298 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
299 #define MEMBERSIZE(s, member, nextmember) \
300 (offsetof(s, nextmember) - offsetof(s, member))
302 /* Decodes the items in a sequence, where the items are described in items,
303 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
304 * pvStructInfo. nextData is a pointer to the memory location at which the
305 * first decoded item with a dynamic pointer should point.
306 * Upon decoding, *cbDecoded is the total number of bytes decoded.
307 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
309 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
310 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
311 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
313 BOOL ret;
314 DWORD i, decoded = 0;
315 const BYTE *ptr = pbEncoded;
317 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
318 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
320 for (i = 0, ret = TRUE; ret && i < cItem; i++)
322 if (cbEncoded - (ptr - pbEncoded) != 0)
324 DWORD itemLen;
326 if ((ret = CRYPT_GetLengthIndefinite(ptr,
327 cbEncoded - (ptr - pbEncoded), &itemLen)))
329 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
331 if (ptr[0] == items[i].tag || !items[i].tag)
333 DWORD itemEncodedLen;
335 if (itemLen == CMSG_INDEFINITE_LENGTH)
336 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
337 else
338 itemEncodedLen = 1 + itemLenBytes + itemLen;
339 if (nextData && pvStructInfo && items[i].hasPointer)
341 TRACE("Setting next pointer to %p\n",
342 nextData);
343 *(BYTE **)((BYTE *)pvStructInfo +
344 items[i].pointerOffset) = nextData;
346 if (items[i].decodeFunc)
348 DWORD itemDecoded;
350 if (pvStructInfo)
351 TRACE("decoding item %d\n", i);
352 else
353 TRACE("sizing item %d\n", i);
354 ret = items[i].decodeFunc(ptr, itemEncodedLen,
355 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
356 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
357 : NULL, &items[i].size, &itemDecoded);
358 if (ret)
360 if (items[i].size < items[i].minSize)
361 items[i].size = items[i].minSize;
362 else if (items[i].size > items[i].minSize)
364 /* Account for alignment padding */
365 items[i].size = ALIGN_DWORD_PTR(items[i].size);
367 TRACE("item %d size: %d\n", i, items[i].size);
368 if (nextData && items[i].hasPointer &&
369 items[i].size > items[i].minSize)
370 nextData += items[i].size - items[i].minSize;
371 if (itemDecoded > itemEncodedLen)
373 WARN("decoded length %d exceeds encoded %d\n",
374 itemDecoded, itemEncodedLen);
375 SetLastError(CRYPT_E_ASN1_CORRUPT);
376 ret = FALSE;
378 else
380 ptr += itemDecoded;
381 decoded += itemDecoded;
382 TRACE("item %d: decoded %d bytes\n", i,
383 itemDecoded);
386 else if (items[i].optional &&
387 GetLastError() == CRYPT_E_ASN1_BADTAG)
389 TRACE("skipping optional item %d\n", i);
390 items[i].size = items[i].minSize;
391 SetLastError(NOERROR);
392 ret = TRUE;
394 else
395 TRACE("item %d failed: %08x\n", i,
396 GetLastError());
398 else if (itemLen == CMSG_INDEFINITE_LENGTH)
400 ERR("can't use indefinite length encoding without a decoder\n");
401 SetLastError(CRYPT_E_ASN1_CORRUPT);
402 ret = FALSE;
404 else
406 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
407 ptr += itemEncodedLen;
408 decoded += itemEncodedLen;
409 items[i].size = items[i].minSize;
412 else if (items[i].optional)
414 TRACE("skipping optional item %d\n", i);
415 items[i].size = items[i].minSize;
417 else
419 TRACE("item %d: tag %02x doesn't match expected %02x\n",
420 i, ptr[0], items[i].tag);
421 SetLastError(CRYPT_E_ASN1_BADTAG);
422 ret = FALSE;
426 else if (items[i].optional)
428 TRACE("missing optional item %d, skipping\n", i);
429 items[i].size = items[i].minSize;
431 else
433 TRACE("not enough bytes for item %d, failing\n", i);
434 SetLastError(CRYPT_E_ASN1_CORRUPT);
435 ret = FALSE;
438 if (cbDecoded)
439 *cbDecoded = decoded;
440 TRACE("returning %d\n", ret);
441 return ret;
444 /* This decodes an arbitrary sequence into a contiguous block of memory
445 * (basically, a struct.) Each element being decoded is described by a struct
446 * AsnDecodeSequenceItem, see above.
447 * startingPointer is an optional pointer to the first place where dynamic
448 * data will be stored. If you know the starting offset, you may pass it
449 * here. Otherwise, pass NULL, and one will be inferred from the items.
451 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
452 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
453 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
454 DWORD *pcbDecoded, void *startingPointer)
456 BOOL ret;
458 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
459 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
460 startingPointer);
462 if (!cbEncoded)
464 SetLastError(CRYPT_E_ASN1_EOD);
465 return FALSE;
467 if (pbEncoded[0] == ASN_SEQUENCE)
469 DWORD dataLen;
471 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
473 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
474 const BYTE *ptr = pbEncoded + 1 + lenBytes;
475 BOOL indefinite = FALSE;
477 cbEncoded -= 1 + lenBytes;
478 if (dataLen == CMSG_INDEFINITE_LENGTH)
480 dataLen = cbEncoded;
481 indefinite = TRUE;
482 lenBytes += 2;
484 else if (cbEncoded < dataLen)
486 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
487 cbEncoded);
488 SetLastError(CRYPT_E_ASN1_CORRUPT);
489 ret = FALSE;
491 if (ret)
493 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
494 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
495 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
497 if (cbDecoded > cbEncoded - 2)
499 /* Not enough space for 0 TLV */
500 SetLastError(CRYPT_E_ASN1_CORRUPT);
501 ret = FALSE;
503 else if (*(ptr + cbDecoded) != 0 ||
504 *(ptr + cbDecoded + 1) != 0)
506 TRACE("expected 0 TLV\n");
507 SetLastError(CRYPT_E_ASN1_CORRUPT);
508 ret = FALSE;
510 else
511 cbDecoded += 2;
514 if (ret && !indefinite && cbDecoded != dataLen)
516 TRACE("expected %d decoded, got %d, failing\n", dataLen,
517 cbDecoded);
518 SetLastError(CRYPT_E_ASN1_CORRUPT);
519 ret = FALSE;
521 if (ret)
523 DWORD i, bytesNeeded = 0, structSize = 0;
525 for (i = 0; i < cItem; i++)
527 if (items[i].size > items[i].minSize)
528 bytesNeeded += items[i].size - items[i].minSize;
529 structSize = max( structSize, items[i].offset + items[i].minSize );
531 bytesNeeded += structSize;
532 if (pcbDecoded)
533 *pcbDecoded = 1 + lenBytes + cbDecoded;
534 if (!pvStructInfo)
535 *pcbStructInfo = bytesNeeded;
536 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
537 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
539 BYTE *nextData;
541 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
542 pvStructInfo = *(BYTE **)pvStructInfo;
543 if (startingPointer)
544 nextData = startingPointer;
545 else
546 nextData = (BYTE *)pvStructInfo + structSize;
547 memset(pvStructInfo, 0, structSize);
548 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
549 ptr, dataLen, dwFlags, pvStructInfo, nextData,
550 &cbDecoded);
551 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
552 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
557 else
559 SetLastError(CRYPT_E_ASN1_BADTAG);
560 ret = FALSE;
562 TRACE("returning %d (%08x)\n", ret, GetLastError());
563 return ret;
566 /* tag:
567 * The expected tag of the entire encoded array (usually a variant
568 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
569 * regardless of the tag seen.
570 * countOffset:
571 * The offset within the outer structure at which the count exists.
572 * For example, a structure such as CRYPT_ATTRIBUTES has countOffset == 0,
573 * while CRYPT_ATTRIBUTE has countOffset ==
574 * offsetof(CRYPT_ATTRIBUTE, cValue).
575 * arrayOffset:
576 * The offset within the outer structure at which the array pointer exists.
577 * For example, CRYPT_ATTRIBUTES has arrayOffset ==
578 * offsetof(CRYPT_ATTRIBUTES, rgAttr).
579 * minArraySize:
580 * The minimum size of the decoded array. On WIN32, this is always 8:
581 * sizeof(DWORD) + sizeof(void *). On WIN64, it can be larger due to
582 * alignment.
583 * decodeFunc:
584 * used to decode each item in the array
585 * itemSize:
586 * is the minimum size of each decoded item
587 * hasPointer:
588 * indicates whether each item has a dynamic pointer
589 * pointerOffset:
590 * indicates the offset within itemSize at which the pointer exists
592 struct AsnArrayDescriptor
594 BYTE tag;
595 DWORD countOffset;
596 DWORD arrayOffset;
597 DWORD minArraySize;
598 InternalDecodeFunc decodeFunc;
599 DWORD itemSize;
600 BOOL hasPointer;
601 DWORD pointerOffset;
604 struct AsnArrayItemSize
606 DWORD encodedLen;
607 DWORD size;
610 /* Decodes an array of like types into a structure described by a struct
611 * AsnArrayDescriptor.
613 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
614 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
615 const CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
616 DWORD *pcbDecoded)
618 BOOL ret = TRUE;
620 TRACE("%p, %p, %d, %p, %d\n", arrayDesc, pbEncoded,
621 cbEncoded, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
623 if (!cbEncoded)
625 SetLastError(CRYPT_E_ASN1_EOD);
626 ret = FALSE;
628 else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
630 DWORD dataLen;
632 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
634 DWORD bytesNeeded = arrayDesc->minArraySize, cItems = 0, decoded;
635 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
636 /* There can be arbitrarily many items, but there is often only one.
638 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
640 decoded = 1 + lenBytes;
641 if (dataLen)
643 const BYTE *ptr;
644 BOOL doneDecoding = FALSE;
646 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
648 if (dataLen == CMSG_INDEFINITE_LENGTH)
650 if (ptr[0] == 0)
652 doneDecoding = TRUE;
653 if (ptr[1] != 0)
655 SetLastError(CRYPT_E_ASN1_CORRUPT);
656 ret = FALSE;
658 else
659 decoded += 2;
662 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
663 doneDecoding = TRUE;
664 if (!doneDecoding)
666 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
668 /* Each item decoded may not tolerate extraneous bytes,
669 * so get the length of the next element if known.
671 if ((ret = CRYPT_GetLengthIndefinite(ptr,
672 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
674 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
675 itemEncoded = cbEncoded - (ptr - pbEncoded);
676 else
677 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
678 itemDataLen;
680 if (ret)
681 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
682 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
683 &itemDecoded);
684 if (ret)
686 /* Ignore an item that failed to decode but the decoder doesn't want to fail the whole process */
687 if (!size)
689 ptr += itemEncoded;
690 continue;
693 cItems++;
694 if (itemSizes != &itemSize)
695 itemSizes = CryptMemRealloc(itemSizes,
696 cItems * sizeof(struct AsnArrayItemSize));
697 else if (cItems > 1)
699 itemSizes =
700 CryptMemAlloc(
701 cItems * sizeof(struct AsnArrayItemSize));
702 if (itemSizes)
703 *itemSizes = itemSize;
705 if (itemSizes)
707 decoded += itemDecoded;
708 itemSizes[cItems - 1].encodedLen = itemEncoded;
709 itemSizes[cItems - 1].size = size;
710 bytesNeeded += size;
711 ptr += itemEncoded;
713 else
714 ret = FALSE;
719 if (ret)
721 if (pcbDecoded)
722 *pcbDecoded = decoded;
723 if (!pvStructInfo)
724 *pcbStructInfo = bytesNeeded;
725 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
726 pvStructInfo, pcbStructInfo, bytesNeeded)))
728 DWORD i, *pcItems;
729 BYTE *nextData;
730 const BYTE *ptr;
731 void *rgItems;
733 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
734 pvStructInfo = *(void **)pvStructInfo;
735 pcItems = pvStructInfo;
736 *pcItems = cItems;
737 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
739 rgItems = (BYTE *)pvStructInfo +
740 arrayDesc->minArraySize;
741 *(void **)((BYTE *)pcItems -
742 arrayDesc->countOffset + arrayDesc->arrayOffset) =
743 rgItems;
745 else
746 rgItems = *(void **)((BYTE *)pcItems -
747 arrayDesc->countOffset + arrayDesc->arrayOffset);
748 nextData = (BYTE *)rgItems + cItems * arrayDesc->itemSize;
749 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
750 i < cItems && ptr - pbEncoded - 1 - lenBytes <
751 dataLen; i++)
753 DWORD itemDecoded;
755 if (arrayDesc->hasPointer)
756 *(BYTE **)((BYTE *)rgItems + i * arrayDesc->itemSize
757 + arrayDesc->pointerOffset) = nextData;
758 ret = arrayDesc->decodeFunc(ptr,
759 itemSizes[i].encodedLen,
760 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
761 (BYTE *)rgItems + i * arrayDesc->itemSize,
762 &itemSizes[i].size, &itemDecoded);
763 if (ret)
765 nextData += itemSizes[i].size - arrayDesc->itemSize;
766 ptr += itemDecoded;
769 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
770 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
773 if (itemSizes != &itemSize)
774 CryptMemFree(itemSizes);
777 else
779 SetLastError(CRYPT_E_ASN1_BADTAG);
780 ret = FALSE;
782 return ret;
785 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
786 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
787 * to CRYPT_E_ASN1_CORRUPT.
788 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
789 * set!
791 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
792 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
794 BOOL ret;
795 DWORD dataLen;
797 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
799 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
800 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
802 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
803 bytesNeeded += 1 + lenBytes + dataLen;
805 if (pcbDecoded)
806 *pcbDecoded = 1 + lenBytes + dataLen;
807 if (!pvStructInfo)
808 *pcbStructInfo = bytesNeeded;
809 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
811 CRYPT_DER_BLOB *blob;
813 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
814 pvStructInfo = *(BYTE **)pvStructInfo;
815 blob = pvStructInfo;
816 blob->cbData = 1 + lenBytes + dataLen;
817 if (blob->cbData)
819 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
820 blob->pbData = (BYTE *)pbEncoded;
821 else
823 assert(blob->pbData);
824 memcpy(blob->pbData, pbEncoded, blob->cbData);
827 else
829 SetLastError(CRYPT_E_ASN1_CORRUPT);
830 ret = FALSE;
834 return ret;
837 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
838 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
839 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
840 DWORD *pcbDecoded)
842 BOOL ret;
844 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
845 pvStructInfo, *pcbStructInfo, pcbDecoded);
847 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
848 * place.
850 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
851 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
852 pcbDecoded);
853 if (ret && pvStructInfo)
855 CRYPT_BIT_BLOB *blob = pvStructInfo;
857 if (blob->cbData)
859 DWORD i;
860 BYTE temp;
862 for (i = 0; i < blob->cbData / 2; i++)
864 temp = blob->pbData[i];
865 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
866 blob->pbData[blob->cbData - i - 1] = temp;
870 TRACE("returning %d (%08x)\n", ret, GetLastError());
871 return ret;
874 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
875 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
876 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
878 BOOL ret = TRUE;
880 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
881 pDecodePara, pvStructInfo, *pcbStructInfo);
883 __TRY
885 struct AsnDecodeSequenceItem items[] = {
886 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
887 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
888 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
889 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
890 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
891 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
892 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
893 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
894 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
895 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
898 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
899 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
900 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
901 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
902 pcbStructInfo, NULL, NULL);
904 __EXCEPT_PAGE_FAULT
906 SetLastError(STATUS_ACCESS_VIOLATION);
907 ret = FALSE;
909 __ENDTRY
911 TRACE("Returning %d (%08x)\n", ret, GetLastError());
912 return ret;
915 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
916 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
918 BOOL ret;
919 DWORD dataLen;
921 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
923 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
925 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
926 dwFlags, pvStructInfo, pcbStructInfo, NULL);
927 if (pcbDecoded)
928 *pcbDecoded = 1 + lenBytes + dataLen;
930 return ret;
933 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
934 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
936 BOOL ret;
938 struct AsnDecodeSequenceItem items[] = {
939 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
940 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
941 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
942 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
945 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
946 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
947 pcbDecoded, NULL);
948 return ret;
951 static BOOL CRYPT_AsnDecodeCertExtensionsInternal(const BYTE *pbEncoded,
952 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
953 DWORD *pcbDecoded)
955 BOOL ret = TRUE;
956 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
957 offsetof(CERT_INFO, cExtension), offsetof(CERT_INFO, rgExtension),
958 FINALMEMBERSIZE(CERT_INFO, cExtension),
959 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
960 offsetof(CERT_EXTENSION, pszObjId) };
962 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
963 pvStructInfo, *pcbStructInfo, pcbDecoded);
965 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
966 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
967 return ret;
970 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
971 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
972 DWORD *pcbDecoded)
974 BOOL ret;
975 DWORD dataLen;
977 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
979 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
981 ret = CRYPT_AsnDecodeCertExtensionsInternal(pbEncoded + 1 + lenBytes,
982 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
983 if (ret && pcbDecoded)
984 *pcbDecoded = 1 + lenBytes + dataLen;
986 return ret;
989 static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
990 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
991 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
993 BOOL ret = TRUE;
994 struct AsnDecodeSequenceItem items[] = {
995 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
996 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
997 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
998 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
999 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
1000 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
1001 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1002 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
1003 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1004 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1005 Issuer.pbData) },
1006 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
1007 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
1008 FALSE, 0 },
1009 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
1010 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1011 Subject.pbData) },
1012 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
1013 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
1014 FALSE, TRUE, offsetof(CERT_INFO,
1015 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
1016 { ASN_CONTEXT | 1, offsetof(CERT_INFO, IssuerUniqueId),
1017 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1018 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
1019 { ASN_CONTEXT | 2, offsetof(CERT_INFO, SubjectUniqueId),
1020 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1021 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
1022 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
1023 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(CERT_INFO, cExtension),
1024 TRUE, TRUE, offsetof(CERT_INFO, rgExtension), 0 },
1027 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1028 pDecodePara, pvStructInfo, *pcbStructInfo);
1030 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1031 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1032 NULL, NULL);
1033 if (ret && pvStructInfo)
1035 CERT_INFO *info;
1037 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1038 info = *(CERT_INFO **)pvStructInfo;
1039 else
1040 info = pvStructInfo;
1041 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1042 !info->Subject.cbData)
1044 SetLastError(CRYPT_E_ASN1_CORRUPT);
1045 /* Don't need to deallocate, because it should have failed on the
1046 * first pass (and no memory was allocated.)
1048 ret = FALSE;
1052 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1053 return ret;
1056 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1057 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1058 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1060 BOOL ret = FALSE;
1062 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1063 pDecodePara, pvStructInfo, *pcbStructInfo);
1065 __TRY
1067 DWORD size = 0;
1069 /* Unless told not to, first try to decode it as a signed cert. */
1070 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1072 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1074 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1075 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1076 &signedCert, &size);
1077 if (ret)
1079 size = 0;
1080 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1081 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1082 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1083 pvStructInfo, pcbStructInfo);
1084 LocalFree(signedCert);
1087 /* Failing that, try it as an unsigned cert */
1088 if (!ret)
1090 size = 0;
1091 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1092 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1093 pDecodePara, pvStructInfo, pcbStructInfo);
1096 __EXCEPT_PAGE_FAULT
1098 SetLastError(STATUS_ACCESS_VIOLATION);
1100 __ENDTRY
1102 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1103 return ret;
1106 static BOOL CRYPT_AsnDecodeCRLEntryExtensions(const BYTE *pbEncoded,
1107 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1108 DWORD *pcbDecoded)
1110 BOOL ret = TRUE;
1111 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1112 offsetof(CRL_ENTRY, cExtension), offsetof(CRL_ENTRY, rgExtension),
1113 FINALMEMBERSIZE(CRL_ENTRY, cExtension),
1114 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1115 offsetof(CERT_EXTENSION, pszObjId) };
1117 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1118 pvStructInfo, *pcbStructInfo, pcbDecoded);
1120 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1121 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1122 return ret;
1125 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1126 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1128 BOOL ret;
1129 struct AsnDecodeSequenceItem items[] = {
1130 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1131 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1132 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1133 { 0, offsetof(CRL_ENTRY, RevocationDate),
1134 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1135 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1136 CRYPT_AsnDecodeCRLEntryExtensions,
1137 FINALMEMBERSIZE(CRL_ENTRY, cExtension), TRUE, TRUE,
1138 offsetof(CRL_ENTRY, rgExtension), 0 },
1140 PCRL_ENTRY entry = pvStructInfo;
1142 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1143 *pcbStructInfo);
1145 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1146 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1147 entry ? entry->SerialNumber.pbData : NULL);
1148 if (ret && entry && !entry->SerialNumber.cbData)
1150 WARN("empty CRL entry serial number\n");
1151 SetLastError(CRYPT_E_ASN1_CORRUPT);
1152 ret = FALSE;
1154 return ret;
1157 /* Warning: assumes pvStructInfo points to the cCRLEntry member of a CRL_INFO
1158 * whose rgCRLEntry member has been set prior to calling.
1160 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1161 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1163 BOOL ret;
1164 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1165 offsetof(CRL_INFO, cCRLEntry), offsetof(CRL_INFO, rgCRLEntry),
1166 MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1167 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1168 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1170 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1171 pvStructInfo, *pcbStructInfo, pcbDecoded);
1173 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1174 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1175 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1176 return ret;
1179 static BOOL CRYPT_AsnDecodeCRLExtensionsInternal(const BYTE *pbEncoded,
1180 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1181 DWORD *pcbDecoded)
1183 BOOL ret = TRUE;
1184 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1185 offsetof(CRL_INFO, cExtension), offsetof(CRL_INFO, rgExtension),
1186 FINALMEMBERSIZE(CRL_INFO, cExtension),
1187 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1188 offsetof(CERT_EXTENSION, pszObjId) };
1190 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1191 pvStructInfo, *pcbStructInfo, pcbDecoded);
1193 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1194 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1195 return ret;
1198 static BOOL CRYPT_AsnDecodeCRLExtensions(const BYTE *pbEncoded,
1199 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1200 DWORD *pcbDecoded)
1202 BOOL ret;
1203 DWORD dataLen;
1205 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1207 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1209 ret = CRYPT_AsnDecodeCRLExtensionsInternal(pbEncoded + 1 + lenBytes,
1210 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
1211 if (ret && pcbDecoded)
1212 *pcbDecoded = 1 + lenBytes + dataLen;
1214 return ret;
1217 static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1218 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1219 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1221 struct AsnDecodeSequenceItem items[] = {
1222 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1223 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1224 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1225 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1226 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1227 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1228 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1229 Issuer.pbData) },
1230 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1231 sizeof(FILETIME), FALSE, FALSE, 0 },
1232 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1233 sizeof(FILETIME), TRUE, FALSE, 0 },
1234 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1235 CRYPT_AsnDecodeCRLEntries, MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1236 TRUE, TRUE, offsetof(CRL_INFO, rgCRLEntry), 0 },
1237 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1238 CRYPT_AsnDecodeCRLExtensions, FINALMEMBERSIZE(CRL_INFO, cExtension),
1239 TRUE, TRUE, offsetof(CRL_INFO, rgExtension), 0 },
1241 BOOL ret = TRUE;
1243 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1244 pDecodePara, pvStructInfo, *pcbStructInfo);
1246 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags,
1247 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1249 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1250 return ret;
1253 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1254 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1255 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1257 BOOL ret = FALSE;
1259 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1260 pDecodePara, pvStructInfo, *pcbStructInfo);
1262 __TRY
1264 DWORD size = 0;
1266 /* Unless told not to, first try to decode it as a signed crl. */
1267 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1269 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1271 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1272 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1273 &signedCrl, &size);
1274 if (ret)
1276 size = 0;
1277 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1278 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1279 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1280 pvStructInfo, pcbStructInfo);
1281 LocalFree(signedCrl);
1284 /* Failing that, try it as an unsigned crl */
1285 if (!ret)
1287 size = 0;
1288 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1289 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1290 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1293 __EXCEPT_PAGE_FAULT
1295 SetLastError(STATUS_ACCESS_VIOLATION);
1297 __ENDTRY
1299 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1300 return ret;
1303 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1304 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1306 BOOL ret = TRUE;
1307 DWORD dataLen;
1309 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1310 pvStructInfo, *pcbStructInfo);
1312 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1314 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1315 DWORD bytesNeeded = sizeof(LPSTR);
1317 if (dataLen)
1319 const BYTE *ptr;
1320 char str[32];
1322 snprintf(str, sizeof(str), "%d.%d",
1323 pbEncoded[1 + lenBytes] / 40,
1324 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1325 * 40);
1326 bytesNeeded += strlen(str) + 1;
1327 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1328 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1330 int val = 0;
1332 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1333 (*ptr & 0x80))
1335 val <<= 7;
1336 val |= *ptr & 0x7f;
1337 ptr++;
1339 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1340 (*ptr & 0x80))
1342 SetLastError(CRYPT_E_ASN1_CORRUPT);
1343 ret = FALSE;
1345 else
1347 val <<= 7;
1348 val |= *ptr++;
1349 snprintf(str, sizeof(str), ".%d", val);
1350 bytesNeeded += strlen(str);
1354 if (pcbDecoded)
1355 *pcbDecoded = 1 + lenBytes + dataLen;
1356 if (!pvStructInfo)
1357 *pcbStructInfo = bytesNeeded;
1358 else if (*pcbStructInfo < bytesNeeded)
1360 *pcbStructInfo = bytesNeeded;
1361 SetLastError(ERROR_MORE_DATA);
1362 ret = FALSE;
1364 else
1366 if (dataLen)
1368 const BYTE *ptr;
1369 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1371 *pszObjId = 0;
1372 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1373 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1374 40) * 40);
1375 pszObjId += strlen(pszObjId);
1376 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1377 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1379 int val = 0;
1381 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1382 (*ptr & 0x80))
1384 val <<= 7;
1385 val |= *ptr & 0x7f;
1386 ptr++;
1388 val <<= 7;
1389 val |= *ptr++;
1390 sprintf(pszObjId, ".%d", val);
1391 pszObjId += strlen(pszObjId);
1394 else
1395 *(LPSTR *)pvStructInfo = NULL;
1396 *pcbStructInfo = bytesNeeded;
1399 return ret;
1402 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1403 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1405 BOOL ret;
1407 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1408 pvStructInfo, *pcbStructInfo);
1410 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1411 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1412 pvStructInfo, pcbStructInfo, pcbDecoded);
1413 else
1415 SetLastError(CRYPT_E_ASN1_BADTAG);
1416 ret = FALSE;
1418 return ret;
1421 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1422 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1424 struct AsnDecodeSequenceItem items[] = {
1425 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1426 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1427 offsetof(CERT_EXTENSION, pszObjId), 0 },
1428 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1429 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1430 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1431 CRYPT_AsnDecodeOctets, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1432 offsetof(CERT_EXTENSION, Value.pbData) },
1434 BOOL ret = TRUE;
1435 PCERT_EXTENSION ext = pvStructInfo;
1437 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1438 *pcbStructInfo);
1440 if (ext)
1441 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1442 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1443 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1444 pcbDecoded, ext ? ext->pszObjId : NULL);
1445 if (ext)
1446 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1447 debugstr_a(ext->pszObjId));
1448 TRACE("returning %d (%08x)\n", ret, GetLastError());
1449 return ret;
1452 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1453 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1454 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1456 BOOL ret = TRUE;
1458 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1459 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
1461 __TRY
1463 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1464 offsetof(CERT_EXTENSIONS, cExtension),
1465 offsetof(CERT_EXTENSIONS, rgExtension),
1466 sizeof(CERT_EXTENSIONS),
1467 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1468 offsetof(CERT_EXTENSION, pszObjId) };
1469 CERT_EXTENSIONS *exts = pvStructInfo;
1471 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1472 exts->rgExtension = (CERT_EXTENSION *)(exts + 1);
1473 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1474 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1476 __EXCEPT_PAGE_FAULT
1478 SetLastError(STATUS_ACCESS_VIOLATION);
1479 ret = FALSE;
1481 __ENDTRY
1482 return ret;
1485 /* Warning: this assumes the address of value->Value.pbData is already set, in
1486 * order to avoid overwriting memory. (In some cases, it may change it, if it
1487 * doesn't copy anything to memory.) Be sure to set it correctly!
1489 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1490 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1491 DWORD *pcbDecoded)
1493 BOOL ret = TRUE;
1494 DWORD dataLen;
1495 CERT_NAME_VALUE *value = pvStructInfo;
1497 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1499 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1500 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1502 switch (pbEncoded[0])
1504 case ASN_OCTETSTRING:
1505 valueType = CERT_RDN_OCTET_STRING;
1506 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1507 bytesNeeded += dataLen;
1508 break;
1509 case ASN_NUMERICSTRING:
1510 valueType = CERT_RDN_NUMERIC_STRING;
1511 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1512 bytesNeeded += dataLen;
1513 break;
1514 case ASN_PRINTABLESTRING:
1515 valueType = CERT_RDN_PRINTABLE_STRING;
1516 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1517 bytesNeeded += dataLen;
1518 break;
1519 case ASN_IA5STRING:
1520 valueType = CERT_RDN_IA5_STRING;
1521 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1522 bytesNeeded += dataLen;
1523 break;
1524 case ASN_T61STRING:
1525 valueType = CERT_RDN_T61_STRING;
1526 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1527 bytesNeeded += dataLen;
1528 break;
1529 case ASN_VIDEOTEXSTRING:
1530 valueType = CERT_RDN_VIDEOTEX_STRING;
1531 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1532 bytesNeeded += dataLen;
1533 break;
1534 case ASN_GRAPHICSTRING:
1535 valueType = CERT_RDN_GRAPHIC_STRING;
1536 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1537 bytesNeeded += dataLen;
1538 break;
1539 case ASN_VISIBLESTRING:
1540 valueType = CERT_RDN_VISIBLE_STRING;
1541 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1542 bytesNeeded += dataLen;
1543 break;
1544 case ASN_GENERALSTRING:
1545 valueType = CERT_RDN_GENERAL_STRING;
1546 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1547 bytesNeeded += dataLen;
1548 break;
1549 case ASN_UNIVERSALSTRING:
1550 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1551 SetLastError(CRYPT_E_ASN1_BADTAG);
1552 return FALSE;
1553 case ASN_BMPSTRING:
1554 valueType = CERT_RDN_BMP_STRING;
1555 bytesNeeded += dataLen;
1556 break;
1557 case ASN_UTF8STRING:
1558 valueType = CERT_RDN_UTF8_STRING;
1559 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1560 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * sizeof(WCHAR);
1561 break;
1562 default:
1563 SetLastError(CRYPT_E_ASN1_BADTAG);
1564 return FALSE;
1567 if (pcbDecoded)
1568 *pcbDecoded = 1 + lenBytes + dataLen;
1569 if (!value)
1570 *pcbStructInfo = bytesNeeded;
1571 else if (*pcbStructInfo < bytesNeeded)
1573 *pcbStructInfo = bytesNeeded;
1574 SetLastError(ERROR_MORE_DATA);
1575 ret = FALSE;
1577 else
1579 *pcbStructInfo = bytesNeeded;
1580 value->dwValueType = valueType;
1581 if (dataLen)
1583 DWORD i;
1585 assert(value->Value.pbData);
1586 switch (pbEncoded[0])
1588 case ASN_OCTETSTRING:
1589 case ASN_NUMERICSTRING:
1590 case ASN_PRINTABLESTRING:
1591 case ASN_IA5STRING:
1592 case ASN_T61STRING:
1593 case ASN_VIDEOTEXSTRING:
1594 case ASN_GRAPHICSTRING:
1595 case ASN_VISIBLESTRING:
1596 case ASN_GENERALSTRING:
1597 value->Value.cbData = dataLen;
1598 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1599 memcpy(value->Value.pbData,
1600 pbEncoded + 1 + lenBytes, dataLen);
1601 else
1602 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1603 lenBytes;
1604 break;
1605 case ASN_BMPSTRING:
1607 LPWSTR str = (LPWSTR)value->Value.pbData;
1609 value->Value.cbData = dataLen;
1610 for (i = 0; i < dataLen / 2; i++)
1611 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1612 pbEncoded[1 + lenBytes + 2 * i + 1];
1613 break;
1615 case ASN_UTF8STRING:
1617 LPWSTR str = (LPWSTR)value->Value.pbData;
1619 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1620 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1621 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1622 break;
1626 else
1628 value->Value.cbData = 0;
1629 value->Value.pbData = NULL;
1633 return ret;
1636 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1637 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1638 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1640 BOOL ret = TRUE;
1642 __TRY
1644 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1645 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1646 if (ret && pvStructInfo)
1648 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1649 pcbStructInfo, *pcbStructInfo);
1650 if (ret)
1652 CERT_NAME_VALUE *value;
1654 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1655 pvStructInfo = *(BYTE **)pvStructInfo;
1656 value = pvStructInfo;
1657 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1658 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1659 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1660 pcbStructInfo, NULL);
1661 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1662 CRYPT_FreeSpace(pDecodePara, value);
1666 __EXCEPT_PAGE_FAULT
1668 SetLastError(STATUS_ACCESS_VIOLATION);
1669 ret = FALSE;
1671 __ENDTRY
1672 return ret;
1675 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1676 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1677 DWORD *pcbDecoded)
1679 BOOL ret = TRUE;
1680 DWORD dataLen;
1681 CERT_NAME_VALUE *value = pvStructInfo;
1683 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1685 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1686 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1688 switch (pbEncoded[0])
1690 case ASN_NUMERICSTRING:
1691 valueType = CERT_RDN_NUMERIC_STRING;
1692 if (dataLen)
1693 bytesNeeded += (dataLen + 1) * 2;
1694 break;
1695 case ASN_PRINTABLESTRING:
1696 valueType = CERT_RDN_PRINTABLE_STRING;
1697 if (dataLen)
1698 bytesNeeded += (dataLen + 1) * 2;
1699 break;
1700 case ASN_IA5STRING:
1701 valueType = CERT_RDN_IA5_STRING;
1702 if (dataLen)
1703 bytesNeeded += (dataLen + 1) * 2;
1704 break;
1705 case ASN_T61STRING:
1706 valueType = CERT_RDN_T61_STRING;
1707 if (dataLen)
1708 bytesNeeded += (dataLen + 1) * 2;
1709 break;
1710 case ASN_VIDEOTEXSTRING:
1711 valueType = CERT_RDN_VIDEOTEX_STRING;
1712 if (dataLen)
1713 bytesNeeded += (dataLen + 1) * 2;
1714 break;
1715 case ASN_GRAPHICSTRING:
1716 valueType = CERT_RDN_GRAPHIC_STRING;
1717 if (dataLen)
1718 bytesNeeded += (dataLen + 1) * 2;
1719 break;
1720 case ASN_VISIBLESTRING:
1721 valueType = CERT_RDN_VISIBLE_STRING;
1722 if (dataLen)
1723 bytesNeeded += (dataLen + 1) * 2;
1724 break;
1725 case ASN_GENERALSTRING:
1726 valueType = CERT_RDN_GENERAL_STRING;
1727 if (dataLen)
1728 bytesNeeded += (dataLen + 1) * 2;
1729 break;
1730 case ASN_UNIVERSALSTRING:
1731 valueType = CERT_RDN_UNIVERSAL_STRING;
1732 if (dataLen)
1733 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
1734 break;
1735 case ASN_BMPSTRING:
1736 valueType = CERT_RDN_BMP_STRING;
1737 if (dataLen)
1738 bytesNeeded += dataLen + sizeof(WCHAR);
1739 break;
1740 case ASN_UTF8STRING:
1741 valueType = CERT_RDN_UTF8_STRING;
1742 if (dataLen)
1743 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
1744 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
1745 break;
1746 default:
1747 SetLastError(CRYPT_E_ASN1_BADTAG);
1748 return FALSE;
1751 if (pcbDecoded)
1752 *pcbDecoded = 1 + lenBytes + dataLen;
1753 if (!value)
1754 *pcbStructInfo = bytesNeeded;
1755 else if (*pcbStructInfo < bytesNeeded)
1757 *pcbStructInfo = bytesNeeded;
1758 SetLastError(ERROR_MORE_DATA);
1759 ret = FALSE;
1761 else
1763 *pcbStructInfo = bytesNeeded;
1764 value->dwValueType = valueType;
1765 if (dataLen)
1767 DWORD i;
1768 LPWSTR str = (LPWSTR)value->Value.pbData;
1770 assert(value->Value.pbData);
1771 switch (pbEncoded[0])
1773 case ASN_NUMERICSTRING:
1774 case ASN_PRINTABLESTRING:
1775 case ASN_IA5STRING:
1776 case ASN_T61STRING:
1777 case ASN_VIDEOTEXSTRING:
1778 case ASN_GRAPHICSTRING:
1779 case ASN_VISIBLESTRING:
1780 case ASN_GENERALSTRING:
1781 value->Value.cbData = dataLen * 2;
1782 for (i = 0; i < dataLen; i++)
1783 str[i] = pbEncoded[1 + lenBytes + i];
1784 str[i] = 0;
1785 break;
1786 case ASN_UNIVERSALSTRING:
1787 value->Value.cbData = dataLen / 2;
1788 for (i = 0; i < dataLen / 4; i++)
1789 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1790 | pbEncoded[1 + lenBytes + 2 * i + 3];
1791 str[i] = 0;
1792 break;
1793 case ASN_BMPSTRING:
1794 value->Value.cbData = dataLen;
1795 for (i = 0; i < dataLen / 2; i++)
1796 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1797 pbEncoded[1 + lenBytes + 2 * i + 1];
1798 str[i] = 0;
1799 break;
1800 case ASN_UTF8STRING:
1801 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1802 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1803 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR);
1804 *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0;
1805 value->Value.cbData += sizeof(WCHAR);
1806 break;
1809 else
1811 value->Value.cbData = 0;
1812 value->Value.pbData = NULL;
1816 return ret;
1819 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1820 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1821 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1823 BOOL ret = TRUE;
1825 __TRY
1827 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1828 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1829 if (ret && pvStructInfo)
1831 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1832 pcbStructInfo, *pcbStructInfo);
1833 if (ret)
1835 CERT_NAME_VALUE *value;
1837 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1838 pvStructInfo = *(BYTE **)pvStructInfo;
1839 value = pvStructInfo;
1840 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1841 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1842 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1843 pcbStructInfo, NULL);
1844 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1845 CRYPT_FreeSpace(pDecodePara, value);
1849 __EXCEPT_PAGE_FAULT
1851 SetLastError(STATUS_ACCESS_VIOLATION);
1852 ret = FALSE;
1854 __ENDTRY
1855 return ret;
1858 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1859 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1861 BOOL ret;
1862 struct AsnDecodeSequenceItem items[] = {
1863 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1864 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1865 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1866 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1867 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1868 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1870 CERT_RDN_ATTR *attr = pvStructInfo;
1872 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1873 pvStructInfo, *pcbStructInfo);
1875 if (attr)
1876 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1877 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1878 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1879 attr ? attr->pszObjId : NULL);
1880 if (attr)
1882 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1883 debugstr_a(attr->pszObjId));
1884 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1886 TRACE("returning %d (%08x)\n", ret, GetLastError());
1887 return ret;
1890 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1891 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1893 BOOL ret = TRUE;
1894 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1895 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1896 sizeof(CERT_RDN),
1897 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1898 offsetof(CERT_RDN_ATTR, pszObjId) };
1900 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1901 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1902 return ret;
1905 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1906 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1907 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1909 BOOL ret = TRUE;
1911 __TRY
1913 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1914 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
1915 sizeof(CERT_NAME_INFO),
1916 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1917 offsetof(CERT_RDN, rgRDNAttr) };
1918 DWORD bytesNeeded = 0;
1920 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1921 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
1922 NULL);
1923 if (ret)
1925 if (!pvStructInfo)
1926 *pcbStructInfo = bytesNeeded;
1927 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1928 pvStructInfo, pcbStructInfo, bytesNeeded)))
1930 CERT_NAME_INFO *info;
1932 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1933 pvStructInfo = *(BYTE **)pvStructInfo;
1934 info = pvStructInfo;
1935 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
1936 sizeof(CERT_NAME_INFO));
1937 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1938 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1939 &bytesNeeded, NULL);
1940 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1941 CRYPT_FreeSpace(pDecodePara, info);
1945 __EXCEPT_PAGE_FAULT
1947 SetLastError(STATUS_ACCESS_VIOLATION);
1948 ret = FALSE;
1950 __ENDTRY
1951 return ret;
1954 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1955 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1956 DWORD *pcbDecoded)
1958 BOOL ret;
1959 struct AsnDecodeSequenceItem items[] = {
1960 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1961 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1962 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1963 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1964 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1965 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1967 CERT_RDN_ATTR *attr = pvStructInfo;
1969 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1970 pvStructInfo, *pcbStructInfo);
1972 if (attr)
1973 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1974 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1975 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1976 attr ? attr->pszObjId : NULL);
1977 if (attr)
1979 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1980 debugstr_a(attr->pszObjId));
1981 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1983 TRACE("returning %d (%08x)\n", ret, GetLastError());
1984 return ret;
1987 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1988 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1990 BOOL ret = TRUE;
1991 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1992 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1993 sizeof(CERT_RDN),
1994 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1995 offsetof(CERT_RDN_ATTR, pszObjId) };
1997 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1998 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1999 return ret;
2002 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
2003 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2004 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2006 BOOL ret = TRUE;
2008 __TRY
2010 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2011 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
2012 sizeof(CERT_NAME_INFO),
2013 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
2014 offsetof(CERT_RDN, rgRDNAttr) };
2015 DWORD bytesNeeded = 0;
2017 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2018 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
2019 NULL);
2020 if (ret)
2022 if (!pvStructInfo)
2023 *pcbStructInfo = bytesNeeded;
2024 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2025 pvStructInfo, pcbStructInfo, bytesNeeded)))
2027 CERT_NAME_INFO *info;
2029 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2030 pvStructInfo = *(BYTE **)pvStructInfo;
2031 info = pvStructInfo;
2032 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
2033 sizeof(CERT_NAME_INFO));
2034 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2035 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2036 &bytesNeeded, NULL);
2037 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2038 CRYPT_FreeSpace(pDecodePara, info);
2042 __EXCEPT_PAGE_FAULT
2044 SetLastError(STATUS_ACCESS_VIOLATION);
2045 ret = FALSE;
2047 __ENDTRY
2048 return ret;
2051 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
2052 DWORD *pcbDecoded)
2054 BOOL ret = TRUE, done = FALSE;
2055 DWORD indefiniteNestingLevels = 0, decoded = 0;
2057 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
2059 do {
2060 DWORD dataLen;
2062 if (!cbEncoded)
2063 done = TRUE;
2064 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
2065 &dataLen)))
2067 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2069 if (dataLen == CMSG_INDEFINITE_LENGTH)
2071 indefiniteNestingLevels++;
2072 pbEncoded += 1 + lenBytes;
2073 cbEncoded -= 1 + lenBytes;
2074 decoded += 1 + lenBytes;
2075 TRACE("indefiniteNestingLevels = %d\n",
2076 indefiniteNestingLevels);
2078 else
2080 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
2081 indefiniteNestingLevels)
2083 indefiniteNestingLevels--;
2084 TRACE("indefiniteNestingLevels = %d\n",
2085 indefiniteNestingLevels);
2087 pbEncoded += 1 + lenBytes + dataLen;
2088 cbEncoded -= 1 + lenBytes + dataLen;
2089 decoded += 1 + lenBytes + dataLen;
2090 if (!indefiniteNestingLevels)
2091 done = TRUE;
2094 } while (ret && !done);
2095 /* If we haven't found all 0 TLVs, we haven't found the end */
2096 if (ret && indefiniteNestingLevels)
2098 SetLastError(CRYPT_E_ASN1_EOD);
2099 ret = FALSE;
2101 if (ret)
2102 *pcbDecoded = decoded;
2103 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
2104 return ret;
2107 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
2108 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2109 DWORD *pcbDecoded)
2111 BOOL ret = TRUE;
2112 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
2114 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2115 pvStructInfo, *pcbStructInfo);
2117 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
2119 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2120 bytesNeeded += encodedLen;
2121 if (!pvStructInfo)
2122 *pcbStructInfo = bytesNeeded;
2123 else if (*pcbStructInfo < bytesNeeded)
2125 SetLastError(ERROR_MORE_DATA);
2126 *pcbStructInfo = bytesNeeded;
2127 ret = FALSE;
2129 else
2131 PCRYPT_OBJID_BLOB blob = pvStructInfo;
2133 *pcbStructInfo = bytesNeeded;
2134 blob->cbData = encodedLen;
2135 if (encodedLen)
2137 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2138 blob->pbData = (LPBYTE)pbEncoded;
2139 else
2141 assert(blob->pbData);
2142 memcpy(blob->pbData, pbEncoded, blob->cbData);
2145 else
2146 blob->pbData = NULL;
2148 if (pcbDecoded)
2149 *pcbDecoded = encodedLen;
2151 return ret;
2154 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2155 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2157 BOOL ret;
2158 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2159 offsetof(CTL_USAGE, cUsageIdentifier),
2160 offsetof(CTL_USAGE, rgpszUsageIdentifier),
2161 sizeof(CTL_USAGE),
2162 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2164 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2165 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2166 return ret;
2169 static BOOL CRYPT_AsnDecodeCTLEntryAttributes(const BYTE *pbEncoded,
2170 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2171 DWORD *pcbDecoded)
2173 struct AsnArrayDescriptor arrayDesc = { 0,
2174 offsetof(CTL_ENTRY, cAttribute), offsetof(CTL_ENTRY, rgAttribute),
2175 FINALMEMBERSIZE(CTL_ENTRY, cAttribute),
2176 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2177 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2178 BOOL ret;
2180 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2181 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2182 return ret;
2185 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2186 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2188 struct AsnDecodeSequenceItem items[] = {
2189 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2190 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2191 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2192 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2193 CRYPT_AsnDecodeCTLEntryAttributes,
2194 FINALMEMBERSIZE(CTL_ENTRY, cAttribute), FALSE, TRUE,
2195 offsetof(CTL_ENTRY, rgAttribute), 0 },
2197 BOOL ret = TRUE;
2198 CTL_ENTRY *entry = pvStructInfo;
2200 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2201 *pcbStructInfo);
2203 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2204 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2205 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2206 return ret;
2209 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2210 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2212 BOOL ret;
2213 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2214 offsetof(CTL_INFO, cCTLEntry), offsetof(CTL_INFO, rgCTLEntry),
2215 FINALMEMBERSIZE(CTL_INFO, cExtension),
2216 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2217 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2219 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2220 pvStructInfo, *pcbStructInfo, pcbDecoded);
2222 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2223 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2224 return ret;
2227 static BOOL CRYPT_AsnDecodeCTLExtensionsInternal(const BYTE *pbEncoded,
2228 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2229 DWORD *pcbDecoded)
2231 BOOL ret = TRUE;
2232 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2233 offsetof(CTL_INFO, cExtension), offsetof(CTL_INFO, rgExtension),
2234 FINALMEMBERSIZE(CTL_INFO, cExtension),
2235 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
2236 offsetof(CERT_EXTENSION, pszObjId) };
2238 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2239 pvStructInfo, *pcbStructInfo, pcbDecoded);
2241 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2242 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2243 return ret;
2246 static BOOL CRYPT_AsnDecodeCTLExtensions(const BYTE *pbEncoded,
2247 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2248 DWORD *pcbDecoded)
2250 BOOL ret;
2251 DWORD dataLen;
2253 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2255 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2257 ret = CRYPT_AsnDecodeCTLExtensionsInternal(pbEncoded + 1 + lenBytes,
2258 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2259 if (ret && pcbDecoded)
2260 *pcbDecoded = 1 + lenBytes + dataLen;
2262 return ret;
2265 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2266 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2267 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2269 BOOL ret = FALSE;
2271 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2272 pDecodePara, pvStructInfo, *pcbStructInfo);
2274 __TRY
2276 struct AsnDecodeSequenceItem items[] = {
2277 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2278 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2279 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2280 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2281 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2282 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2283 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), TRUE,
2284 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2285 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2286 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2287 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2288 { 0, offsetof(CTL_INFO, ThisUpdate),
2289 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2290 0 },
2291 { 0, offsetof(CTL_INFO, NextUpdate),
2292 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2293 0 },
2294 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2295 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2296 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2297 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2298 CRYPT_AsnDecodeCTLEntries,
2299 MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension),
2300 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2301 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2302 CRYPT_AsnDecodeCTLExtensions, FINALMEMBERSIZE(CTL_INFO, cExtension),
2303 TRUE, TRUE, offsetof(CTL_INFO, rgExtension), 0 },
2306 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2307 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2308 pcbStructInfo, NULL, NULL);
2310 __EXCEPT_PAGE_FAULT
2312 SetLastError(STATUS_ACCESS_VIOLATION);
2314 __ENDTRY
2315 return ret;
2318 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2319 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2320 DWORD *pcbDecoded)
2322 BOOL ret;
2323 struct AsnDecodeSequenceItem items[] = {
2324 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2325 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2326 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2327 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2328 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2329 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2331 PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
2333 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2334 pvStructInfo, *pcbStructInfo);
2336 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2337 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2338 pcbDecoded, capability ? capability->pszObjId : NULL);
2339 TRACE("returning %d\n", ret);
2340 return ret;
2343 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2344 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2345 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2347 BOOL ret = FALSE;
2349 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2350 pDecodePara, pvStructInfo, *pcbStructInfo);
2352 __TRY
2354 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2355 offsetof(CRYPT_SMIME_CAPABILITIES, cCapability),
2356 offsetof(CRYPT_SMIME_CAPABILITIES, rgCapability),
2357 sizeof(CRYPT_SMIME_CAPABILITIES),
2358 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2359 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2360 CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
2362 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2363 capabilities->rgCapability = (CRYPT_SMIME_CAPABILITY *)(capabilities + 1);
2364 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2365 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2367 __EXCEPT_PAGE_FAULT
2369 SetLastError(STATUS_ACCESS_VIOLATION);
2371 __ENDTRY
2372 TRACE("returning %d\n", ret);
2373 return ret;
2376 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
2377 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2378 DWORD *pcbDecoded)
2380 BOOL ret = TRUE;
2381 DWORD dataLen;
2382 LPSTR *pStr = pvStructInfo;
2384 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2386 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2387 DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
2389 if (pbEncoded[0] != ASN_IA5STRING)
2391 SetLastError(CRYPT_E_ASN1_CORRUPT);
2392 ret = FALSE;
2394 else
2396 bytesNeeded += dataLen;
2397 if (pcbDecoded)
2398 *pcbDecoded = 1 + lenBytes + dataLen;
2399 if (!pvStructInfo)
2400 *pcbStructInfo = bytesNeeded;
2401 else if (*pcbStructInfo < bytesNeeded)
2403 *pcbStructInfo = bytesNeeded;
2404 SetLastError(ERROR_MORE_DATA);
2405 ret = FALSE;
2407 else
2409 *pcbStructInfo = bytesNeeded;
2410 if (dataLen)
2412 LPSTR str = *pStr;
2414 assert(str);
2415 memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
2416 str[dataLen] = 0;
2418 else
2419 *pStr = NULL;
2423 return ret;
2426 static BOOL CRYPT_AsnDecodeNoticeNumbers(const BYTE *pbEncoded,
2427 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2428 DWORD *pcbDecoded)
2430 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2431 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2432 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, rgNoticeNumbers),
2433 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2434 CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
2435 BOOL ret;
2437 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2438 pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
2440 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2441 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2442 TRACE("returning %d\n", ret);
2443 return ret;
2446 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
2447 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2448 DWORD *pcbDecoded)
2450 BOOL ret;
2451 struct AsnDecodeSequenceItem items[] = {
2452 { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2453 pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
2454 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
2455 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2456 cNoticeNumbers), CRYPT_AsnDecodeNoticeNumbers,
2457 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2458 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2459 rgNoticeNumbers), 0 },
2461 DWORD bytesNeeded = 0;
2463 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2464 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2466 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2467 pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
2468 NULL);
2469 if (ret)
2471 /* The caller is expecting a pointer to a
2472 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
2473 * CRYPT_AsnDecodeSequence is decoding a
2474 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. Increment the bytes
2475 * needed, and decode again if the requisite space is available.
2477 bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
2478 if (!pvStructInfo)
2479 *pcbStructInfo = bytesNeeded;
2480 else if (*pcbStructInfo < bytesNeeded)
2482 *pcbStructInfo = bytesNeeded;
2483 SetLastError(ERROR_MORE_DATA);
2484 ret = FALSE;
2486 else
2488 PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
2490 *pcbStructInfo = bytesNeeded;
2491 /* The pointer (pvStructInfo) passed in points to the first dynamic
2492 * pointer, so use it as the pointer to the
2493 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
2494 * appropriate offset for the first dynamic pointer within the
2495 * notice reference by pointing to the first memory location past
2496 * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
2498 noticeRef =
2499 *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
2500 noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
2501 sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
2502 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags,
2503 NULL, noticeRef, &bytesNeeded, pcbDecoded, noticeRef->pszOrganization);
2506 TRACE("returning %d\n", ret);
2507 return ret;
2510 static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
2511 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2512 DWORD *pcbDecoded)
2514 BOOL ret = TRUE;
2515 DWORD dataLen;
2517 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2519 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2520 DWORD bytesNeeded = sizeof(LPWSTR);
2522 switch (pbEncoded[0])
2524 case ASN_NUMERICSTRING:
2525 if (dataLen)
2526 bytesNeeded += (dataLen + 1) * 2;
2527 break;
2528 case ASN_PRINTABLESTRING:
2529 if (dataLen)
2530 bytesNeeded += (dataLen + 1) * 2;
2531 break;
2532 case ASN_IA5STRING:
2533 if (dataLen)
2534 bytesNeeded += (dataLen + 1) * 2;
2535 break;
2536 case ASN_T61STRING:
2537 if (dataLen)
2538 bytesNeeded += (dataLen + 1) * 2;
2539 break;
2540 case ASN_VIDEOTEXSTRING:
2541 if (dataLen)
2542 bytesNeeded += (dataLen + 1) * 2;
2543 break;
2544 case ASN_GRAPHICSTRING:
2545 if (dataLen)
2546 bytesNeeded += (dataLen + 1) * 2;
2547 break;
2548 case ASN_VISIBLESTRING:
2549 if (dataLen)
2550 bytesNeeded += (dataLen + 1) * 2;
2551 break;
2552 case ASN_GENERALSTRING:
2553 if (dataLen)
2554 bytesNeeded += (dataLen + 1) * 2;
2555 break;
2556 case ASN_UNIVERSALSTRING:
2557 if (dataLen)
2558 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
2559 break;
2560 case ASN_BMPSTRING:
2561 if (dataLen)
2562 bytesNeeded += dataLen + sizeof(WCHAR);
2563 break;
2564 case ASN_UTF8STRING:
2565 if (dataLen)
2566 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
2567 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
2568 break;
2569 default:
2570 SetLastError(CRYPT_E_ASN1_BADTAG);
2571 return FALSE;
2574 if (pcbDecoded)
2575 *pcbDecoded = 1 + lenBytes + dataLen;
2576 if (!pvStructInfo)
2577 *pcbStructInfo = bytesNeeded;
2578 else if (*pcbStructInfo < bytesNeeded)
2580 *pcbStructInfo = bytesNeeded;
2581 SetLastError(ERROR_MORE_DATA);
2582 ret = FALSE;
2584 else
2586 LPWSTR *pStr = pvStructInfo;
2588 *pcbStructInfo = bytesNeeded;
2589 if (dataLen)
2591 DWORD i;
2592 LPWSTR str = *pStr;
2594 assert(str);
2595 switch (pbEncoded[0])
2597 case ASN_NUMERICSTRING:
2598 case ASN_PRINTABLESTRING:
2599 case ASN_IA5STRING:
2600 case ASN_T61STRING:
2601 case ASN_VIDEOTEXSTRING:
2602 case ASN_GRAPHICSTRING:
2603 case ASN_VISIBLESTRING:
2604 case ASN_GENERALSTRING:
2605 for (i = 0; i < dataLen; i++)
2606 str[i] = pbEncoded[1 + lenBytes + i];
2607 str[i] = 0;
2608 break;
2609 case ASN_UNIVERSALSTRING:
2610 for (i = 0; i < dataLen / 4; i++)
2611 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2612 | pbEncoded[1 + lenBytes + 2 * i + 3];
2613 str[i] = 0;
2614 break;
2615 case ASN_BMPSTRING:
2616 for (i = 0; i < dataLen / 2; i++)
2617 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2618 pbEncoded[1 + lenBytes + 2 * i + 1];
2619 str[i] = 0;
2620 break;
2621 case ASN_UTF8STRING:
2623 int len = MultiByteToWideChar(CP_UTF8, 0,
2624 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2625 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
2626 str[len] = 0;
2627 break;
2631 else
2632 *pStr = NULL;
2635 return ret;
2638 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2639 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2640 DWORD *pcbStructInfo, DWORD *pcbDecoded)
2642 BOOL ret;
2643 struct AsnDecodeSequenceItem items[] = {
2644 { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2645 pNoticeReference), CRYPT_AsnDecodeNoticeReference,
2646 sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
2647 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
2648 { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
2649 CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
2650 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
2652 PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
2654 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2655 pvStructInfo, *pcbStructInfo);
2657 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2658 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2659 pcbDecoded, notice ? notice->pNoticeReference : NULL);
2660 TRACE("returning %d\n", ret);
2661 return ret;
2664 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
2665 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2666 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2667 void *pvStructInfo, DWORD *pcbStructInfo)
2669 BOOL ret = FALSE;
2671 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2672 pDecodePara, pvStructInfo, *pcbStructInfo);
2674 __TRY
2676 DWORD bytesNeeded = 0;
2678 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
2679 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2680 NULL);
2681 if (ret)
2683 if (!pvStructInfo)
2684 *pcbStructInfo = bytesNeeded;
2685 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2686 pvStructInfo, pcbStructInfo, bytesNeeded)))
2688 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
2690 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2691 pvStructInfo = *(BYTE **)pvStructInfo;
2692 notice = pvStructInfo;
2693 notice->pNoticeReference =
2694 (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
2695 ((BYTE *)pvStructInfo +
2696 sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
2697 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2698 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
2699 pvStructInfo, &bytesNeeded, NULL);
2700 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2701 CRYPT_FreeSpace(pDecodePara, notice);
2705 __EXCEPT_PAGE_FAULT
2707 SetLastError(STATUS_ACCESS_VIOLATION);
2709 __ENDTRY
2710 TRACE("returning %d\n", ret);
2711 return ret;
2714 static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded,
2715 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2716 DWORD *pcbDecoded)
2718 BOOL ret;
2719 struct AsnArrayDescriptor arrayDesc = { 0,
2720 offsetof(CRYPT_ATTRIBUTE, cValue), offsetof(CRYPT_ATTRIBUTE, rgValue),
2721 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue),
2722 CRYPT_AsnDecodeCopyBytes,
2723 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2725 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2726 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
2728 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2729 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2730 return ret;
2733 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2734 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2735 DWORD *pcbDecoded)
2737 BOOL ret;
2738 struct AsnDecodeSequenceItem items[] = {
2739 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2740 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2741 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2742 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2743 CRYPT_AsnDecodePKCSAttributeValue,
2744 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE,
2745 TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2747 PCRYPT_ATTRIBUTE attr = pvStructInfo;
2749 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2750 pvStructInfo, *pcbStructInfo);
2752 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2753 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2754 pcbDecoded, attr ? attr->pszObjId : NULL);
2755 TRACE("returning %d\n", ret);
2756 return ret;
2759 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2760 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2761 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2763 BOOL ret = FALSE;
2765 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2766 pDecodePara, pvStructInfo, *pcbStructInfo);
2768 __TRY
2770 DWORD bytesNeeded = 0;
2772 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2773 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2774 if (ret)
2776 if (!pvStructInfo)
2777 *pcbStructInfo = bytesNeeded;
2778 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2779 pvStructInfo, pcbStructInfo, bytesNeeded)))
2781 PCRYPT_ATTRIBUTE attr;
2783 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2784 pvStructInfo = *(BYTE **)pvStructInfo;
2785 attr = pvStructInfo;
2786 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2787 sizeof(CRYPT_ATTRIBUTE));
2788 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2789 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2790 NULL);
2791 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2792 CRYPT_FreeSpace(pDecodePara, attr);
2796 __EXCEPT_PAGE_FAULT
2798 SetLastError(STATUS_ACCESS_VIOLATION);
2800 __ENDTRY
2801 TRACE("returning %d\n", ret);
2802 return ret;
2805 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2806 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2807 DWORD *pcbDecoded)
2809 struct AsnArrayDescriptor arrayDesc = { 0,
2810 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2811 sizeof(CRYPT_ATTRIBUTES),
2812 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2813 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2814 BOOL ret;
2816 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2817 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2818 return ret;
2821 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2822 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2823 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2825 BOOL ret = FALSE;
2827 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2828 pDecodePara, pvStructInfo, *pcbStructInfo);
2830 __TRY
2832 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
2833 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2834 sizeof(CRYPT_ATTRIBUTES),
2835 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE),
2836 TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2837 CRYPT_ATTRIBUTES *attrs = pvStructInfo;
2839 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2840 attrs->rgAttr = (CRYPT_ATTRIBUTE *)(attrs + 1);
2841 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2842 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2844 __EXCEPT_PAGE_FAULT
2846 SetLastError(STATUS_ACCESS_VIOLATION);
2848 __ENDTRY
2849 TRACE("returning %d\n", ret);
2850 return ret;
2853 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2854 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2856 CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
2857 BOOL ret = TRUE;
2858 struct AsnDecodeSequenceItem items[] = {
2859 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2860 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2861 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2862 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2863 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2864 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2867 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2868 pvStructInfo, *pcbStructInfo, pcbDecoded);
2870 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2871 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2872 pcbDecoded, algo ? algo->pszObjId : NULL);
2873 if (ret && pvStructInfo)
2875 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2876 debugstr_a(algo->pszObjId));
2878 return ret;
2881 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2882 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2883 DWORD *pcbDecoded)
2885 BOOL ret = TRUE;
2886 struct AsnDecodeSequenceItem items[] = {
2887 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2888 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2889 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2890 Algorithm.pszObjId) },
2891 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2892 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2893 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2895 PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
2897 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2898 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2899 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2900 return ret;
2903 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2904 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2905 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2907 BOOL ret = TRUE;
2909 __TRY
2911 DWORD bytesNeeded = 0;
2913 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2914 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2916 if (!pvStructInfo)
2917 *pcbStructInfo = bytesNeeded;
2918 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2919 pvStructInfo, pcbStructInfo, bytesNeeded)))
2921 PCERT_PUBLIC_KEY_INFO info;
2923 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2924 pvStructInfo = *(BYTE **)pvStructInfo;
2925 info = pvStructInfo;
2926 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2927 sizeof(CERT_PUBLIC_KEY_INFO);
2928 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2929 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2930 &bytesNeeded, NULL);
2931 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2932 CRYPT_FreeSpace(pDecodePara, info);
2936 __EXCEPT_PAGE_FAULT
2938 SetLastError(STATUS_ACCESS_VIOLATION);
2939 ret = FALSE;
2941 __ENDTRY
2942 return ret;
2945 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2946 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2948 BOOL ret;
2950 if (cbEncoded < 3)
2952 SetLastError(CRYPT_E_ASN1_CORRUPT);
2953 return FALSE;
2955 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2957 SetLastError(CRYPT_E_ASN1_CORRUPT);
2958 return FALSE;
2960 if (pbEncoded[1] > 1)
2962 SetLastError(CRYPT_E_ASN1_CORRUPT);
2963 return FALSE;
2965 if (pcbDecoded)
2966 *pcbDecoded = 3;
2967 if (!pvStructInfo)
2969 *pcbStructInfo = sizeof(BOOL);
2970 ret = TRUE;
2972 else if (*pcbStructInfo < sizeof(BOOL))
2974 *pcbStructInfo = sizeof(BOOL);
2975 SetLastError(ERROR_MORE_DATA);
2976 ret = FALSE;
2978 else
2980 *pcbStructInfo = sizeof(BOOL);
2981 *(BOOL *)pvStructInfo = pbEncoded[2] != 0;
2982 ret = TRUE;
2984 TRACE("returning %d (%08x)\n", ret, GetLastError());
2985 return ret;
2988 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2989 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2991 PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
2992 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2993 BOOL ret;
2995 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2996 pvStructInfo, *pcbStructInfo);
2998 if (cbEncoded < 2)
3000 SetLastError(CRYPT_E_ASN1_CORRUPT);
3001 return FALSE;
3003 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3004 if (1 + lenBytes > cbEncoded)
3006 SetLastError(CRYPT_E_ASN1_CORRUPT);
3007 return FALSE;
3009 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3011 switch (pbEncoded[0] & ASN_TYPE_MASK)
3013 case 1: /* rfc822Name */
3014 case 2: /* dNSName */
3015 case 6: /* uniformResourceIdentifier */
3016 if (memchr(pbEncoded + 1 + lenBytes, 0, dataLen))
3018 SetLastError(CRYPT_E_ASN1_RULE);
3019 ret = FALSE;
3021 else
3022 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
3023 break;
3024 case 4: /* directoryName */
3025 case 7: /* iPAddress */
3026 bytesNeeded += dataLen;
3027 break;
3028 case 8: /* registeredID */
3029 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
3030 &dataLen, NULL);
3031 if (ret)
3033 /* FIXME: ugly, shouldn't need to know internals of OID decode
3034 * function to use it.
3036 bytesNeeded += dataLen - sizeof(LPSTR);
3038 break;
3039 case 0: /* otherName */
3040 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
3041 SetLastError(CRYPT_E_ASN1_BADTAG);
3042 ret = FALSE;
3043 break;
3044 case 3: /* x400Address, unimplemented */
3045 case 5: /* ediPartyName, unimplemented */
3046 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
3047 SetLastError(CRYPT_E_ASN1_BADTAG);
3048 ret = FALSE;
3049 break;
3050 default:
3051 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
3052 SetLastError(CRYPT_E_ASN1_CORRUPT);
3053 ret = FALSE;
3055 if (ret)
3057 if (pcbDecoded)
3058 *pcbDecoded = 1 + lenBytes + dataLen;
3059 if (!entry)
3060 *pcbStructInfo = bytesNeeded;
3061 else if (*pcbStructInfo < bytesNeeded)
3063 *pcbStructInfo = bytesNeeded;
3064 SetLastError(ERROR_MORE_DATA);
3065 ret = FALSE;
3067 else
3069 *pcbStructInfo = bytesNeeded;
3070 /* MS used values one greater than the asn1 ones.. sigh */
3071 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
3072 switch (pbEncoded[0] & ASN_TYPE_MASK)
3074 case 1: /* rfc822Name */
3075 case 2: /* dNSName */
3076 case 6: /* uniformResourceIdentifier */
3078 DWORD i;
3080 for (i = 0; i < dataLen; i++)
3081 entry->u.pwszURL[i] =
3082 (WCHAR)pbEncoded[1 + lenBytes + i];
3083 entry->u.pwszURL[i] = 0;
3084 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
3085 debugstr_w(entry->u.pwszURL));
3086 break;
3088 case 4: /* directoryName */
3089 /* The data are memory-equivalent with the IPAddress case,
3090 * fall-through
3092 case 7: /* iPAddress */
3093 /* The next data pointer is in the pwszURL spot, that is,
3094 * the first 4 bytes. Need to move it to the next spot.
3096 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
3097 entry->u.IPAddress.cbData = dataLen;
3098 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
3099 dataLen);
3100 break;
3101 case 8: /* registeredID */
3102 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
3103 &entry->u.pszRegisteredID, &dataLen, NULL);
3104 break;
3109 return ret;
3112 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
3113 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3114 DWORD *pcbDecoded)
3116 BOOL ret;
3117 struct AsnArrayDescriptor arrayDesc = { 0,
3118 offsetof(CERT_ALT_NAME_INFO, cAltEntry),
3119 offsetof(CERT_ALT_NAME_INFO, rgAltEntry),
3120 sizeof(CERT_ALT_NAME_INFO),
3121 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3122 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3124 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3125 pvStructInfo, *pcbStructInfo, pcbDecoded);
3127 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3128 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3129 return ret;
3132 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
3133 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3134 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3136 BOOL ret;
3138 __TRY
3140 struct AsnDecodeSequenceItem items[] = {
3141 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
3142 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB),
3143 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
3144 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3145 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
3146 CRYPT_AsnDecodeOctets, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
3147 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
3148 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
3149 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3150 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3151 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
3154 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3155 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3156 pcbStructInfo, NULL, NULL);
3158 __EXCEPT_PAGE_FAULT
3160 SetLastError(STATUS_ACCESS_VIOLATION);
3161 ret = FALSE;
3163 __ENDTRY
3164 return ret;
3167 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
3168 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3169 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3171 BOOL ret;
3173 __TRY
3175 struct AsnDecodeSequenceItem items[] = {
3176 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
3177 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB),
3178 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
3179 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3180 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
3181 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
3182 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3183 AuthorityCertIssuer.rgAltEntry), 0 },
3184 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3185 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3186 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3187 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3188 AuthorityCertSerialNumber.pbData), 0 },
3191 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3192 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3193 pcbStructInfo, NULL, NULL);
3195 __EXCEPT_PAGE_FAULT
3197 SetLastError(STATUS_ACCESS_VIOLATION);
3198 ret = FALSE;
3200 __ENDTRY
3201 return ret;
3204 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
3205 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3206 DWORD *pcbDecoded)
3208 struct AsnDecodeSequenceItem items[] = {
3209 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
3210 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3211 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
3212 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
3213 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
3214 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
3216 CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
3218 return CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3219 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3220 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
3223 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
3224 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3225 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3227 BOOL ret;
3229 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3230 pDecodePara, pvStructInfo, *pcbStructInfo);
3232 __TRY
3234 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3235 offsetof(CERT_AUTHORITY_INFO_ACCESS, cAccDescr),
3236 offsetof(CERT_AUTHORITY_INFO_ACCESS, rgAccDescr),
3237 sizeof(CERT_AUTHORITY_INFO_ACCESS),
3238 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
3239 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
3240 CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
3242 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3243 info->rgAccDescr = (CERT_ACCESS_DESCRIPTION *)(info + 1);
3244 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3245 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3247 __EXCEPT_PAGE_FAULT
3249 SetLastError(STATUS_ACCESS_VIOLATION);
3250 ret = FALSE;
3252 __ENDTRY
3253 return ret;
3256 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
3257 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3259 BOOL ret;
3260 DWORD dataLen;
3262 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3263 pvStructInfo, *pcbStructInfo, pcbDecoded);
3265 /* The caller has already checked the tag, no need to check it again.
3266 * Check the outer length is valid:
3268 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
3270 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3271 DWORD innerLen;
3273 pbEncoded += 1 + lenBytes;
3274 cbEncoded -= 1 + lenBytes;
3275 if (dataLen == CMSG_INDEFINITE_LENGTH)
3276 cbEncoded -= 2; /* space for 0 TLV */
3277 /* Check the inner length is valid: */
3278 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
3280 DWORD decodedLen;
3282 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
3283 pvStructInfo, pcbStructInfo, &decodedLen);
3284 if (dataLen == CMSG_INDEFINITE_LENGTH)
3286 if (*(pbEncoded + decodedLen) != 0 ||
3287 *(pbEncoded + decodedLen + 1) != 0)
3289 TRACE("expected 0 TLV, got {%02x,%02x}\n",
3290 *(pbEncoded + decodedLen),
3291 *(pbEncoded + decodedLen + 1));
3292 SetLastError(CRYPT_E_ASN1_CORRUPT);
3293 ret = FALSE;
3295 else
3296 decodedLen += 2;
3298 if (ret && pcbDecoded)
3300 *pcbDecoded = 1 + lenBytes + decodedLen;
3301 TRACE("decoded %d bytes\n", *pcbDecoded);
3305 return ret;
3308 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
3309 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3310 DWORD *pcbDecoded)
3312 CRYPT_CONTENT_INFO *info = pvStructInfo;
3313 struct AsnDecodeSequenceItem items[] = {
3314 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
3315 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3316 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
3317 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
3318 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
3319 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
3320 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
3322 BOOL ret;
3324 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3325 pvStructInfo, *pcbStructInfo, pcbDecoded);
3327 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3328 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3329 pcbDecoded, info ? info->pszObjId : NULL);
3330 return ret;
3333 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
3334 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3335 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3337 BOOL ret = FALSE;
3339 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3340 pDecodePara, pvStructInfo, *pcbStructInfo);
3342 __TRY
3344 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
3345 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3346 if (ret && pvStructInfo)
3348 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3349 pcbStructInfo, *pcbStructInfo);
3350 if (ret)
3352 CRYPT_CONTENT_INFO *info;
3354 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3355 pvStructInfo = *(BYTE **)pvStructInfo;
3356 info = pvStructInfo;
3357 info->pszObjId = (LPSTR)((BYTE *)info +
3358 sizeof(CRYPT_CONTENT_INFO));
3359 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
3360 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3361 pcbStructInfo, NULL);
3362 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3363 CRYPT_FreeSpace(pDecodePara, info);
3367 __EXCEPT_PAGE_FAULT
3369 SetLastError(STATUS_ACCESS_VIOLATION);
3371 __ENDTRY
3372 return ret;
3375 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
3376 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3377 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
3379 BOOL ret;
3380 struct AsnDecodeSequenceItem items[] = {
3381 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
3382 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3383 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
3384 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3385 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
3386 0 },
3387 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
3388 CRYPT_AsnDecodePKCSContentInfoInternal,
3389 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
3390 ContentInfo.pszObjId), 0 },
3391 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
3392 CRYPT_AsnDecodeOctets, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
3393 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
3396 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3397 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
3398 NULL, NULL);
3399 return ret;
3402 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
3403 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3404 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3406 BOOL ret = TRUE;
3408 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3409 pDecodePara, pvStructInfo, *pcbStructInfo);
3411 __TRY
3413 DWORD bytesNeeded = 0;
3415 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3416 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3418 if (!pvStructInfo)
3419 *pcbStructInfo = bytesNeeded;
3420 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3421 pvStructInfo, pcbStructInfo, bytesNeeded)))
3423 CERT_ALT_NAME_INFO *name;
3425 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3426 pvStructInfo = *(BYTE **)pvStructInfo;
3427 name = pvStructInfo;
3428 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
3429 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
3430 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3431 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3432 &bytesNeeded, NULL);
3433 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3434 CRYPT_FreeSpace(pDecodePara, name);
3438 __EXCEPT_PAGE_FAULT
3440 SetLastError(STATUS_ACCESS_VIOLATION);
3441 ret = FALSE;
3443 __ENDTRY
3444 return ret;
3447 struct PATH_LEN_CONSTRAINT
3449 BOOL fPathLenConstraint;
3450 DWORD dwPathLenConstraint;
3453 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3454 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3455 DWORD *pcbDecoded)
3457 BOOL ret = TRUE;
3458 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3460 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3461 pvStructInfo, *pcbStructInfo, pcbDecoded);
3463 if (!pvStructInfo)
3465 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3466 &size, pcbDecoded);
3467 *pcbStructInfo = bytesNeeded;
3469 else if (*pcbStructInfo < bytesNeeded)
3471 SetLastError(ERROR_MORE_DATA);
3472 *pcbStructInfo = bytesNeeded;
3473 ret = FALSE;
3475 else
3477 struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
3479 *pcbStructInfo = bytesNeeded;
3480 size = sizeof(constraint->dwPathLenConstraint);
3481 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3482 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3483 if (ret)
3484 constraint->fPathLenConstraint = TRUE;
3485 TRACE("got an int, dwPathLenConstraint is %d\n",
3486 constraint->dwPathLenConstraint);
3488 TRACE("returning %d (%08x)\n", ret, GetLastError());
3489 return ret;
3492 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3493 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3494 DWORD *pcbDecoded)
3496 BOOL ret;
3497 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3498 offsetof(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3499 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint),
3500 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3501 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3502 offsetof(CERT_NAME_BLOB, pbData) };
3504 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3505 pvStructInfo, *pcbStructInfo, pcbDecoded);
3507 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3508 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3509 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3510 return ret;
3513 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3514 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3515 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3517 BOOL ret;
3519 __TRY
3521 struct AsnDecodeSequenceItem items[] = {
3522 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3523 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3524 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3525 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3526 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3527 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3528 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3529 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3530 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3531 TRUE, TRUE,
3532 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3535 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3536 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3537 pcbStructInfo, NULL, NULL);
3539 __EXCEPT_PAGE_FAULT
3541 SetLastError(STATUS_ACCESS_VIOLATION);
3542 ret = FALSE;
3544 __ENDTRY
3545 return ret;
3548 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3549 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3550 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3552 BOOL ret;
3554 __TRY
3556 struct AsnDecodeSequenceItem items[] = {
3557 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3558 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3559 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3560 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3561 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3564 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3565 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3566 pcbStructInfo, NULL, NULL);
3568 __EXCEPT_PAGE_FAULT
3570 SetLastError(STATUS_ACCESS_VIOLATION);
3571 ret = FALSE;
3573 __ENDTRY
3574 return ret;
3577 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
3578 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3579 DWORD *pcbDecoded)
3581 struct AsnDecodeSequenceItem items[] = {
3582 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
3583 pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3584 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
3585 0 },
3586 { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
3587 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3588 offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
3590 BOOL ret;
3591 CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
3593 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3594 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3596 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3597 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3598 pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
3599 return ret;
3602 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
3603 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3604 DWORD *pcbDecoded)
3606 BOOL ret;
3607 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3608 offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3609 offsetof(CERT_POLICY_INFO, rgPolicyQualifier),
3610 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier),
3611 CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
3612 offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
3614 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3615 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3617 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3618 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3619 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3620 return ret;
3623 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
3624 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3626 struct AsnDecodeSequenceItem items[] = {
3627 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
3628 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3629 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
3630 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3631 CRYPT_AsnDecodePolicyQualifiers,
3632 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier), TRUE,
3633 TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
3635 CERT_POLICY_INFO *info = pvStructInfo;
3636 BOOL ret;
3638 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3639 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3641 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3642 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3643 pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
3644 return ret;
3647 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
3648 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3649 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3651 BOOL ret = FALSE;
3653 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3654 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3656 __TRY
3658 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3659 offsetof(CERT_POLICIES_INFO, cPolicyInfo),
3660 offsetof(CERT_POLICIES_INFO, rgPolicyInfo),
3661 sizeof(CERT_POLICIES_INFO),
3662 CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
3663 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
3664 CERT_POLICIES_INFO *info = pvStructInfo;
3666 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3667 info->rgPolicyInfo = (CERT_POLICY_INFO *)(info + 1);
3669 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3670 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3672 __EXCEPT_PAGE_FAULT
3674 SetLastError(STATUS_ACCESS_VIOLATION);
3676 __ENDTRY
3677 return ret;
3680 static BOOL CRYPT_AsnDecodeCertPolicyMapping(const BYTE *pbEncoded,
3681 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3682 DWORD *pcbDecoded)
3684 struct AsnDecodeSequenceItem items[] = {
3685 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
3686 pszIssuerDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3687 FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy), 0 },
3688 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
3689 pszSubjectDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3690 FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszSubjectDomainPolicy), 0 },
3692 CERT_POLICY_MAPPING *mapping = pvStructInfo;
3693 BOOL ret;
3695 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3696 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3698 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3699 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3700 pcbDecoded, mapping ? mapping->pszIssuerDomainPolicy : NULL);
3701 return ret;
3704 static BOOL WINAPI CRYPT_AsnDecodeCertPolicyMappings(DWORD dwCertEncodingType,
3705 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3706 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3708 BOOL ret = FALSE;
3710 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3711 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3713 __TRY
3715 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3716 offsetof(CERT_POLICY_MAPPINGS_INFO, cPolicyMapping),
3717 offsetof(CERT_POLICY_MAPPINGS_INFO, rgPolicyMapping),
3718 sizeof(CERT_POLICY_MAPPING),
3719 CRYPT_AsnDecodeCertPolicyMapping, sizeof(CERT_POLICY_MAPPING), TRUE,
3720 offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy) };
3721 CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
3723 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3724 info->rgPolicyMapping = (CERT_POLICY_MAPPING *)(info + 1);
3725 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3726 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3728 __EXCEPT_PAGE_FAULT
3730 SetLastError(STATUS_ACCESS_VIOLATION);
3732 __ENDTRY
3733 return ret;
3736 static BOOL CRYPT_AsnDecodeRequireExplicit(const BYTE *pbEncoded,
3737 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3738 DWORD *pcbDecoded)
3740 BOOL ret;
3741 DWORD skip, size = sizeof(skip);
3743 if (!cbEncoded)
3745 SetLastError(CRYPT_E_ASN1_EOD);
3746 return FALSE;
3748 if (pbEncoded[0] != (ASN_CONTEXT | 0))
3750 SetLastError(CRYPT_E_ASN1_BADTAG);
3751 return FALSE;
3753 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3754 &skip, &size, pcbDecoded)))
3756 DWORD bytesNeeded = MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
3757 fRequireExplicitPolicy, fInhibitPolicyMapping);
3759 if (!pvStructInfo)
3760 *pcbStructInfo = bytesNeeded;
3761 else if (*pcbStructInfo < bytesNeeded)
3763 *pcbStructInfo = bytesNeeded;
3764 SetLastError(ERROR_MORE_DATA);
3765 ret = FALSE;
3767 else
3769 CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo,
3770 CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy);
3772 *pcbStructInfo = bytesNeeded;
3773 /* The BOOL is implicit: if the integer is present, then it's
3774 * TRUE.
3776 info->fRequireExplicitPolicy = TRUE;
3777 info->dwRequireExplicitPolicySkipCerts = skip;
3780 return ret;
3783 static BOOL CRYPT_AsnDecodeInhibitMapping(const BYTE *pbEncoded,
3784 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3785 DWORD *pcbDecoded)
3787 BOOL ret;
3788 DWORD skip, size = sizeof(skip);
3790 if (!cbEncoded)
3792 SetLastError(CRYPT_E_ASN1_EOD);
3793 return FALSE;
3795 if (pbEncoded[0] != (ASN_CONTEXT | 1))
3797 SetLastError(CRYPT_E_ASN1_BADTAG);
3798 return FALSE;
3800 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3801 &skip, &size, pcbDecoded)))
3803 DWORD bytesNeeded = FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
3804 fInhibitPolicyMapping);
3806 if (!pvStructInfo)
3807 *pcbStructInfo = bytesNeeded;
3808 else if (*pcbStructInfo < bytesNeeded)
3810 *pcbStructInfo = bytesNeeded;
3811 SetLastError(ERROR_MORE_DATA);
3812 ret = FALSE;
3814 else
3816 CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo,
3817 CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping);
3819 *pcbStructInfo = bytesNeeded;
3820 /* The BOOL is implicit: if the integer is present, then it's
3821 * TRUE.
3823 info->fInhibitPolicyMapping = TRUE;
3824 info->dwInhibitPolicyMappingSkipCerts = skip;
3827 return ret;
3830 static BOOL WINAPI CRYPT_AsnDecodeCertPolicyConstraints(
3831 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3832 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3833 void *pvStructInfo, DWORD *pcbStructInfo)
3835 BOOL ret = FALSE;
3837 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3838 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3840 __TRY
3842 struct AsnDecodeSequenceItem items[] = {
3843 { ASN_CONTEXT | 0,
3844 offsetof(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy),
3845 CRYPT_AsnDecodeRequireExplicit,
3846 MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy,
3847 fInhibitPolicyMapping), TRUE, FALSE, 0, 0 },
3848 { ASN_CONTEXT | 1,
3849 offsetof(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
3850 CRYPT_AsnDecodeInhibitMapping,
3851 FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
3852 TRUE, FALSE, 0, 0 },
3855 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3856 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3857 pcbStructInfo, NULL, NULL);
3859 __EXCEPT_PAGE_FAULT
3861 SetLastError(STATUS_ACCESS_VIOLATION);
3863 __ENDTRY
3864 return ret;
3867 #define RSA1_MAGIC 0x31415352
3869 struct DECODED_RSA_PUB_KEY
3871 DWORD pubexp;
3872 CRYPT_INTEGER_BLOB modulus;
3875 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3876 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3877 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3879 BOOL ret;
3881 __TRY
3883 struct AsnDecodeSequenceItem items[] = {
3884 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3885 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3886 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3887 0 },
3888 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3889 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3891 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3892 DWORD size = 0;
3894 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3895 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3896 &size, NULL, NULL);
3897 if (ret)
3899 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3900 decodedKey->modulus.cbData;
3902 if (!pvStructInfo)
3904 *pcbStructInfo = bytesNeeded;
3905 ret = TRUE;
3907 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3908 pvStructInfo, pcbStructInfo, bytesNeeded)))
3910 BLOBHEADER *hdr;
3911 RSAPUBKEY *rsaPubKey;
3913 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3914 pvStructInfo = *(BYTE **)pvStructInfo;
3915 hdr = pvStructInfo;
3916 hdr->bType = PUBLICKEYBLOB;
3917 hdr->bVersion = CUR_BLOB_VERSION;
3918 hdr->reserved = 0;
3919 hdr->aiKeyAlg = CALG_RSA_KEYX;
3920 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3921 sizeof(BLOBHEADER));
3922 rsaPubKey->magic = RSA1_MAGIC;
3923 rsaPubKey->pubexp = decodedKey->pubexp;
3924 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3925 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3926 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3927 decodedKey->modulus.cbData);
3929 LocalFree(decodedKey);
3932 __EXCEPT_PAGE_FAULT
3934 SetLastError(STATUS_ACCESS_VIOLATION);
3935 ret = FALSE;
3937 __ENDTRY
3938 return ret;
3941 #define RSA2_MAGIC 0x32415352
3943 struct DECODED_RSA_PRIV_KEY
3945 DWORD version;
3946 DWORD pubexp;
3947 CRYPT_INTEGER_BLOB modulus;
3948 CRYPT_INTEGER_BLOB privexp;
3949 CRYPT_INTEGER_BLOB prime1;
3950 CRYPT_INTEGER_BLOB prime2;
3951 CRYPT_INTEGER_BLOB exponent1;
3952 CRYPT_INTEGER_BLOB exponent2;
3953 CRYPT_INTEGER_BLOB coefficient;
3956 static BOOL WINAPI CRYPT_AsnDecodeRsaPrivKey(DWORD dwCertEncodingType,
3957 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3958 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3960 BOOL ret;
3961 DWORD halflen;
3963 __TRY
3965 struct AsnDecodeSequenceItem items[] = {
3966 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, version),
3967 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3968 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, modulus),
3969 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3970 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, modulus.pbData),
3971 0 },
3972 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, pubexp),
3973 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3974 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, privexp),
3975 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3976 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, privexp.pbData),
3977 0 },
3978 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime1),
3979 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3980 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime1.pbData),
3981 0 },
3982 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime2),
3983 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3984 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime2.pbData),
3985 0 },
3986 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1),
3987 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3988 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1.pbData),
3989 0 },
3990 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2),
3991 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3992 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2.pbData),
3993 0 },
3994 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient),
3995 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3996 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient.pbData),
3997 0 },
3999 struct DECODED_RSA_PRIV_KEY *decodedKey = NULL;
4000 DWORD size = 0;
4002 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
4003 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
4004 &size, NULL, NULL);
4005 if (ret)
4007 halflen = decodedKey->prime1.cbData;
4008 if (halflen < decodedKey->prime2.cbData)
4009 halflen = decodedKey->prime2.cbData;
4010 if (halflen < decodedKey->exponent1.cbData)
4011 halflen = decodedKey->exponent1.cbData;
4012 if (halflen < decodedKey->exponent2.cbData)
4013 halflen = decodedKey->exponent2.cbData;
4014 if (halflen < decodedKey->coefficient.cbData)
4015 halflen = decodedKey->coefficient.cbData;
4016 if (halflen * 2 < decodedKey->modulus.cbData)
4017 halflen = decodedKey->modulus.cbData / 2 + decodedKey->modulus.cbData % 2;
4018 if (halflen * 2 < decodedKey->privexp.cbData)
4019 halflen = decodedKey->privexp.cbData / 2 + decodedKey->privexp.cbData % 2;
4021 if (ret)
4023 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
4024 (halflen * 9);
4026 if (!pvStructInfo)
4028 *pcbStructInfo = bytesNeeded;
4029 ret = TRUE;
4031 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4032 pvStructInfo, pcbStructInfo, bytesNeeded)))
4034 BLOBHEADER *hdr;
4035 RSAPUBKEY *rsaPubKey;
4036 BYTE *vardata;
4038 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4039 pvStructInfo = *(BYTE **)pvStructInfo;
4041 hdr = pvStructInfo;
4042 hdr->bType = PRIVATEKEYBLOB;
4043 hdr->bVersion = CUR_BLOB_VERSION;
4044 hdr->reserved = 0;
4045 hdr->aiKeyAlg = CALG_RSA_KEYX;
4047 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
4048 sizeof(BLOBHEADER));
4049 rsaPubKey->magic = RSA2_MAGIC;
4050 rsaPubKey->pubexp = decodedKey->pubexp;
4051 rsaPubKey->bitlen = halflen * 16;
4053 vardata = (BYTE*)(rsaPubKey + 1);
4054 memset(vardata, 0, halflen * 9);
4055 memcpy(vardata,
4056 decodedKey->modulus.pbData, decodedKey->modulus.cbData);
4057 memcpy(vardata + halflen * 2,
4058 decodedKey->prime1.pbData, decodedKey->prime1.cbData);
4059 memcpy(vardata + halflen * 3,
4060 decodedKey->prime2.pbData, decodedKey->prime2.cbData);
4061 memcpy(vardata + halflen * 4,
4062 decodedKey->exponent1.pbData, decodedKey->exponent1.cbData);
4063 memcpy(vardata + halflen * 5,
4064 decodedKey->exponent2.pbData, decodedKey->exponent2.cbData);
4065 memcpy(vardata + halflen * 6,
4066 decodedKey->coefficient.pbData, decodedKey->coefficient.cbData);
4067 memcpy(vardata + halflen * 7,
4068 decodedKey->privexp.pbData, decodedKey->privexp.cbData);
4072 LocalFree(decodedKey);
4075 __EXCEPT_PAGE_FAULT
4077 SetLastError(STATUS_ACCESS_VIOLATION);
4078 ret = FALSE;
4080 __ENDTRY
4081 return ret;
4084 static BOOL CRYPT_AsnDecodeOctets(const BYTE *pbEncoded,
4085 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4086 DWORD *pcbDecoded)
4088 BOOL ret;
4089 DWORD bytesNeeded, dataLen;
4091 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4092 pvStructInfo, *pcbStructInfo, pcbDecoded);
4094 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4096 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4098 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4099 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
4100 else
4101 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
4102 if (pcbDecoded)
4103 *pcbDecoded = 1 + lenBytes + dataLen;
4104 if (!pvStructInfo)
4105 *pcbStructInfo = bytesNeeded;
4106 else if (*pcbStructInfo < bytesNeeded)
4108 SetLastError(ERROR_MORE_DATA);
4109 *pcbStructInfo = bytesNeeded;
4110 ret = FALSE;
4112 else
4114 CRYPT_DATA_BLOB *blob;
4116 *pcbStructInfo = bytesNeeded;
4117 blob = pvStructInfo;
4118 blob->cbData = dataLen;
4119 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4120 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
4121 else
4123 assert(blob->pbData);
4124 if (blob->cbData)
4125 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
4126 blob->cbData);
4130 return ret;
4133 static BOOL CRYPT_AsnDecodeOctetStringInternal(const BYTE *encoded, DWORD encoded_size,
4134 DWORD flags, void *buf, DWORD *buf_size, DWORD *ret_decoded)
4136 DWORD decoded = 0, indefinite_len_depth = 0, len_size, len, bytes_needed;
4137 CRYPT_DATA_BLOB *blob;
4138 const BYTE *string;
4140 while (encoded[0] == (ASN_CONSTRUCTOR | ASN_OCTETSTRING))
4142 if (!CRYPT_GetLengthIndefinite(encoded, encoded_size, &len))
4143 return FALSE;
4145 len_size = GET_LEN_BYTES(encoded[1]);
4146 encoded += 1 + len_size;
4147 encoded_size -= 1 + len_size;
4148 decoded += 1 + len_size;
4150 if (len == CMSG_INDEFINITE_LENGTH)
4152 indefinite_len_depth++;
4153 if (encoded_size < 2)
4155 SetLastError(CRYPT_E_ASN1_EOD);
4156 return FALSE;
4158 encoded_size -= 2;
4159 decoded += 2;
4163 if (encoded[0] != ASN_OCTETSTRING)
4165 WARN("Unexpected tag %02x\n", encoded[0]);
4166 SetLastError(CRYPT_E_ASN1_BADTAG);
4167 return FALSE;
4170 if (!CRYPT_GetLen(encoded, encoded_size, &len))
4171 return FALSE;
4172 len_size = GET_LEN_BYTES(encoded[1]);
4173 decoded += 1 + len_size + len;
4174 encoded_size -= 1 + len_size;
4176 if (len > encoded_size)
4178 SetLastError(CRYPT_E_ASN1_EOD);
4179 return FALSE;
4181 if (ret_decoded)
4182 *ret_decoded = decoded;
4184 encoded += 1 + len_size;
4185 string = encoded;
4186 encoded += len;
4188 while (indefinite_len_depth--)
4190 if (encoded[0] || encoded[1])
4192 TRACE("expected 0 TLV, got %02x %02x\n", encoded[0], encoded[1]);
4193 SetLastError(CRYPT_E_ASN1_CORRUPT);
4194 return FALSE;
4198 bytes_needed = sizeof(*blob);
4199 if (!(flags & CRYPT_DECODE_NOCOPY_FLAG)) bytes_needed += len;
4200 if (!buf)
4202 *buf_size = bytes_needed;
4203 return TRUE;
4205 if (*buf_size < bytes_needed)
4207 SetLastError(ERROR_MORE_DATA);
4208 *buf_size = bytes_needed;
4209 return FALSE;
4212 *buf_size = bytes_needed;
4213 blob = buf;
4214 blob->cbData = len;
4215 if (flags & CRYPT_DECODE_NOCOPY_FLAG)
4216 blob->pbData = (BYTE*)string;
4217 else if (blob->cbData)
4218 memcpy(blob->pbData, string, blob->cbData);
4220 if (ret_decoded)
4221 *ret_decoded = decoded;
4222 return TRUE;
4225 static BOOL WINAPI CRYPT_AsnDecodeOctetString(DWORD dwCertEncodingType,
4226 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4227 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4229 BOOL ret;
4231 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4232 pDecodePara, pvStructInfo, *pcbStructInfo);
4234 if (!cbEncoded)
4236 SetLastError(CRYPT_E_ASN1_CORRUPT);
4237 return FALSE;
4240 __TRY
4242 DWORD bytesNeeded = 0;
4244 if ((ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded,
4245 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4247 if (!pvStructInfo)
4248 *pcbStructInfo = bytesNeeded;
4249 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4250 pvStructInfo, pcbStructInfo, bytesNeeded)))
4252 CRYPT_DATA_BLOB *blob;
4254 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4255 pvStructInfo = *(BYTE **)pvStructInfo;
4256 blob = pvStructInfo;
4257 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
4258 ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded,
4259 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4260 &bytesNeeded, NULL);
4261 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4262 CRYPT_FreeSpace(pDecodePara, blob);
4266 __EXCEPT_PAGE_FAULT
4268 SetLastError(STATUS_ACCESS_VIOLATION);
4269 ret = FALSE;
4271 __ENDTRY
4272 return ret;
4275 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4276 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4278 BOOL ret;
4279 DWORD bytesNeeded, dataLen;
4280 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4282 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
4283 pvStructInfo, *pcbStructInfo, pcbDecoded);
4285 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4287 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4288 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
4289 else
4290 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
4291 if (pcbDecoded)
4292 *pcbDecoded = 1 + lenBytes + dataLen;
4293 if (!pvStructInfo)
4294 *pcbStructInfo = bytesNeeded;
4295 else if (*pcbStructInfo < bytesNeeded)
4297 *pcbStructInfo = bytesNeeded;
4298 SetLastError(ERROR_MORE_DATA);
4299 ret = FALSE;
4301 else
4303 CRYPT_BIT_BLOB *blob;
4305 *pcbStructInfo = bytesNeeded;
4306 blob = pvStructInfo;
4307 blob->cbData = dataLen - 1;
4308 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
4309 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4311 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
4313 else
4315 assert(blob->pbData);
4316 if (blob->cbData)
4318 BYTE mask = 0xff << blob->cUnusedBits;
4320 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
4321 blob->cbData);
4322 blob->pbData[blob->cbData - 1] &= mask;
4327 return ret;
4330 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
4331 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4332 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4334 BOOL ret;
4336 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
4337 pDecodePara, pvStructInfo, pcbStructInfo);
4339 __TRY
4341 DWORD bytesNeeded = 0;
4343 if (!cbEncoded)
4345 SetLastError(CRYPT_E_ASN1_CORRUPT);
4346 ret = FALSE;
4348 else if (pbEncoded[0] != ASN_BITSTRING)
4350 SetLastError(CRYPT_E_ASN1_BADTAG);
4351 ret = FALSE;
4353 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4354 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4356 if (!pvStructInfo)
4357 *pcbStructInfo = bytesNeeded;
4358 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4359 pvStructInfo, pcbStructInfo, bytesNeeded)))
4361 CRYPT_BIT_BLOB *blob;
4363 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4364 pvStructInfo = *(BYTE **)pvStructInfo;
4365 blob = pvStructInfo;
4366 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
4367 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4368 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4369 &bytesNeeded, NULL);
4370 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4371 CRYPT_FreeSpace(pDecodePara, blob);
4375 __EXCEPT_PAGE_FAULT
4377 SetLastError(STATUS_ACCESS_VIOLATION);
4378 ret = FALSE;
4380 __ENDTRY
4381 TRACE("returning %d (%08x)\n", ret, GetLastError());
4382 return ret;
4385 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
4386 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4387 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4389 BOOL ret;
4390 DWORD dataLen;
4392 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4394 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4396 if (pcbDecoded)
4397 *pcbDecoded = 1 + lenBytes + dataLen;
4398 if (dataLen > sizeof(int))
4400 SetLastError(CRYPT_E_ASN1_LARGE);
4401 ret = FALSE;
4403 else if (!pvStructInfo)
4404 *pcbStructInfo = sizeof(int);
4405 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
4407 int val, i;
4409 if (dataLen && pbEncoded[1 + lenBytes] & 0x80)
4411 /* initialize to a negative value to sign-extend */
4412 val = -1;
4414 else
4415 val = 0;
4416 for (i = 0; i < dataLen; i++)
4418 val <<= 8;
4419 val |= pbEncoded[1 + lenBytes + i];
4421 memcpy(pvStructInfo, &val, sizeof(int));
4424 return ret;
4427 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
4428 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4429 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4431 BOOL ret;
4433 __TRY
4435 DWORD bytesNeeded = 0;
4437 if (!cbEncoded)
4439 SetLastError(CRYPT_E_ASN1_EOD);
4440 ret = FALSE;
4442 else if (pbEncoded[0] != ASN_INTEGER)
4444 SetLastError(CRYPT_E_ASN1_BADTAG);
4445 ret = FALSE;
4447 else
4448 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4449 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4450 if (ret)
4452 if (!pvStructInfo)
4453 *pcbStructInfo = bytesNeeded;
4454 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4455 pvStructInfo, pcbStructInfo, bytesNeeded)))
4457 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4458 pvStructInfo = *(BYTE **)pvStructInfo;
4459 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4460 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4461 &bytesNeeded, NULL);
4462 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4463 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
4467 __EXCEPT_PAGE_FAULT
4469 SetLastError(STATUS_ACCESS_VIOLATION);
4470 ret = FALSE;
4472 __ENDTRY
4473 return ret;
4476 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
4477 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4478 DWORD *pcbDecoded)
4480 BOOL ret;
4481 DWORD bytesNeeded, dataLen;
4483 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4485 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4487 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4488 if (pcbDecoded)
4489 *pcbDecoded = 1 + lenBytes + dataLen;
4490 if (!pvStructInfo)
4491 *pcbStructInfo = bytesNeeded;
4492 else if (*pcbStructInfo < bytesNeeded)
4494 *pcbStructInfo = bytesNeeded;
4495 SetLastError(ERROR_MORE_DATA);
4496 ret = FALSE;
4498 else
4500 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4502 *pcbStructInfo = bytesNeeded;
4503 blob->cbData = dataLen;
4504 assert(blob->pbData);
4505 if (blob->cbData)
4507 DWORD i;
4509 for (i = 0; i < blob->cbData; i++)
4511 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4512 dataLen - i - 1);
4517 return ret;
4520 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4521 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4522 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4524 BOOL ret;
4526 __TRY
4528 DWORD bytesNeeded = 0;
4530 if (pbEncoded[0] != ASN_INTEGER)
4532 SetLastError(CRYPT_E_ASN1_BADTAG);
4533 ret = FALSE;
4535 else
4536 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4537 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4538 if (ret)
4540 if (!pvStructInfo)
4541 *pcbStructInfo = bytesNeeded;
4542 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4543 pvStructInfo, pcbStructInfo, bytesNeeded)))
4545 CRYPT_INTEGER_BLOB *blob;
4547 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4548 pvStructInfo = *(BYTE **)pvStructInfo;
4549 blob = pvStructInfo;
4550 blob->pbData = (BYTE *)pvStructInfo +
4551 sizeof(CRYPT_INTEGER_BLOB);
4552 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4553 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4554 &bytesNeeded, NULL);
4555 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4556 CRYPT_FreeSpace(pDecodePara, blob);
4560 __EXCEPT_PAGE_FAULT
4562 SetLastError(STATUS_ACCESS_VIOLATION);
4563 ret = FALSE;
4565 __ENDTRY
4566 return ret;
4569 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
4570 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4571 DWORD *pcbDecoded)
4573 BOOL ret;
4575 if (pbEncoded[0] == ASN_INTEGER)
4577 DWORD bytesNeeded, dataLen;
4579 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4581 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4583 if (pcbDecoded)
4584 *pcbDecoded = 1 + lenBytes + dataLen;
4585 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4586 if (!pvStructInfo)
4587 *pcbStructInfo = bytesNeeded;
4588 else if (*pcbStructInfo < bytesNeeded)
4590 *pcbStructInfo = bytesNeeded;
4591 SetLastError(ERROR_MORE_DATA);
4592 ret = FALSE;
4594 else
4596 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4598 *pcbStructInfo = bytesNeeded;
4599 blob->cbData = dataLen;
4600 assert(blob->pbData);
4601 /* remove leading zero byte if it exists */
4602 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4604 blob->cbData--;
4605 blob->pbData++;
4607 if (blob->cbData)
4609 DWORD i;
4611 for (i = 0; i < blob->cbData; i++)
4613 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4614 dataLen - i - 1);
4620 else
4622 SetLastError(CRYPT_E_ASN1_BADTAG);
4623 ret = FALSE;
4625 return ret;
4628 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4629 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4630 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4632 BOOL ret;
4634 __TRY
4636 DWORD bytesNeeded = 0;
4638 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4639 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4641 if (!pvStructInfo)
4642 *pcbStructInfo = bytesNeeded;
4643 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4644 pvStructInfo, pcbStructInfo, bytesNeeded)))
4646 CRYPT_INTEGER_BLOB *blob;
4648 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4649 pvStructInfo = *(BYTE **)pvStructInfo;
4650 blob = pvStructInfo;
4651 blob->pbData = (BYTE *)pvStructInfo +
4652 sizeof(CRYPT_INTEGER_BLOB);
4653 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4654 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4655 &bytesNeeded, NULL);
4656 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4657 CRYPT_FreeSpace(pDecodePara, blob);
4661 __EXCEPT_PAGE_FAULT
4663 SetLastError(STATUS_ACCESS_VIOLATION);
4664 ret = FALSE;
4666 __ENDTRY
4667 return ret;
4670 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4671 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4672 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4674 BOOL ret;
4676 if (!pvStructInfo)
4678 *pcbStructInfo = sizeof(int);
4679 return TRUE;
4681 __TRY
4683 if (pbEncoded[0] == ASN_ENUMERATED)
4685 unsigned int val = 0, i;
4687 if (cbEncoded <= 1)
4689 SetLastError(CRYPT_E_ASN1_EOD);
4690 ret = FALSE;
4692 else if (pbEncoded[1] == 0)
4694 SetLastError(CRYPT_E_ASN1_CORRUPT);
4695 ret = FALSE;
4697 else
4699 /* A little strange looking, but we have to accept a sign byte:
4700 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4701 * assuming a small length is okay here, it has to be in short
4702 * form.
4704 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4706 SetLastError(CRYPT_E_ASN1_LARGE);
4707 return FALSE;
4709 for (i = 0; i < pbEncoded[1]; i++)
4711 val <<= 8;
4712 val |= pbEncoded[2 + i];
4714 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4715 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4717 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4718 pvStructInfo = *(BYTE **)pvStructInfo;
4719 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4723 else
4725 SetLastError(CRYPT_E_ASN1_BADTAG);
4726 ret = FALSE;
4729 __EXCEPT_PAGE_FAULT
4731 SetLastError(STATUS_ACCESS_VIOLATION);
4732 ret = FALSE;
4734 __ENDTRY
4735 return ret;
4738 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4739 * if it fails.
4741 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4742 do { \
4743 BYTE i; \
4745 (word) = 0; \
4746 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4748 if (!isdigit(*(pbEncoded))) \
4750 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4751 ret = FALSE; \
4753 else \
4755 (word) *= 10; \
4756 (word) += *(pbEncoded)++ - '0'; \
4759 } while (0)
4761 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4762 SYSTEMTIME *sysTime)
4764 BOOL ret = TRUE;
4766 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4768 WORD hours, minutes = 0;
4769 BYTE sign = *pbEncoded++;
4771 len--;
4772 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4773 if (ret && hours >= 24)
4775 SetLastError(CRYPT_E_ASN1_CORRUPT);
4776 ret = FALSE;
4778 else if (len >= 2)
4780 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4781 if (ret && minutes >= 60)
4783 SetLastError(CRYPT_E_ASN1_CORRUPT);
4784 ret = FALSE;
4787 if (ret)
4789 if (sign == '+')
4791 sysTime->wHour += hours;
4792 sysTime->wMinute += minutes;
4794 else
4796 if (hours > sysTime->wHour)
4798 sysTime->wDay--;
4799 sysTime->wHour = 24 - (hours - sysTime->wHour);
4801 else
4802 sysTime->wHour -= hours;
4803 if (minutes > sysTime->wMinute)
4805 sysTime->wHour--;
4806 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4808 else
4809 sysTime->wMinute -= minutes;
4813 return ret;
4816 #define MIN_ENCODED_TIME_LENGTH 10
4818 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4819 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4820 DWORD *pcbDecoded)
4822 BOOL ret = FALSE;
4824 if (pbEncoded[0] == ASN_UTCTIME)
4826 if (cbEncoded <= 1)
4827 SetLastError(CRYPT_E_ASN1_EOD);
4828 else if (pbEncoded[1] > 0x7f)
4830 /* long-form date strings really can't be valid */
4831 SetLastError(CRYPT_E_ASN1_CORRUPT);
4833 else
4835 SYSTEMTIME sysTime = { 0 };
4836 BYTE len = pbEncoded[1];
4838 if (len < MIN_ENCODED_TIME_LENGTH)
4839 SetLastError(CRYPT_E_ASN1_CORRUPT);
4840 else
4842 ret = TRUE;
4843 if (pcbDecoded)
4844 *pcbDecoded = 2 + len;
4845 pbEncoded += 2;
4846 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4847 if (sysTime.wYear >= 50)
4848 sysTime.wYear += 1900;
4849 else
4850 sysTime.wYear += 2000;
4851 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4852 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4853 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4854 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4855 if (ret && len > 0)
4857 if (len >= 2 && isdigit(*pbEncoded) &&
4858 isdigit(*(pbEncoded + 1)))
4859 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4860 sysTime.wSecond);
4861 else if (isdigit(*pbEncoded))
4862 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4863 sysTime.wSecond);
4864 if (ret)
4865 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4866 &sysTime);
4868 if (ret)
4870 if (!pvStructInfo)
4871 *pcbStructInfo = sizeof(FILETIME);
4872 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4873 sizeof(FILETIME))))
4874 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4879 else
4880 SetLastError(CRYPT_E_ASN1_BADTAG);
4881 return ret;
4884 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4885 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4886 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4888 BOOL ret = FALSE;
4890 __TRY
4892 DWORD bytesNeeded = 0;
4894 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4895 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4896 if (ret)
4898 if (!pvStructInfo)
4899 *pcbStructInfo = bytesNeeded;
4900 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4901 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4903 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4904 pvStructInfo = *(BYTE **)pvStructInfo;
4905 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4906 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4907 &bytesNeeded, NULL);
4908 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4909 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
4913 __EXCEPT_PAGE_FAULT
4915 SetLastError(STATUS_ACCESS_VIOLATION);
4917 __ENDTRY
4918 return ret;
4921 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
4922 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4923 DWORD *pcbDecoded)
4925 BOOL ret = FALSE;
4927 if (pbEncoded[0] == ASN_GENERALTIME)
4929 if (cbEncoded <= 1)
4930 SetLastError(CRYPT_E_ASN1_EOD);
4931 else if (pbEncoded[1] > 0x7f)
4933 /* long-form date strings really can't be valid */
4934 SetLastError(CRYPT_E_ASN1_CORRUPT);
4936 else
4938 BYTE len = pbEncoded[1];
4940 if (len < MIN_ENCODED_TIME_LENGTH)
4941 SetLastError(CRYPT_E_ASN1_CORRUPT);
4942 else
4944 SYSTEMTIME sysTime = { 0 };
4946 ret = TRUE;
4947 if (pcbDecoded)
4948 *pcbDecoded = 2 + len;
4949 pbEncoded += 2;
4950 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
4951 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4952 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4953 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4954 if (ret && len > 0)
4956 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4957 sysTime.wMinute);
4958 if (ret && len > 0)
4959 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4960 sysTime.wSecond);
4961 if (ret && len > 0 && (*pbEncoded == '.' ||
4962 *pbEncoded == ','))
4964 BYTE digits;
4966 pbEncoded++;
4967 len--;
4968 /* workaround macro weirdness */
4969 digits = min(len, 3);
4970 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
4971 sysTime.wMilliseconds);
4973 if (ret)
4974 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4975 &sysTime);
4977 if (ret)
4979 if (!pvStructInfo)
4980 *pcbStructInfo = sizeof(FILETIME);
4981 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4982 sizeof(FILETIME))))
4983 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4988 else
4989 SetLastError(CRYPT_E_ASN1_BADTAG);
4990 return ret;
4993 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4994 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4995 DWORD *pcbDecoded)
4997 BOOL ret;
4998 InternalDecodeFunc decode = NULL;
5000 if (pbEncoded[0] == ASN_UTCTIME)
5001 decode = CRYPT_AsnDecodeUtcTimeInternal;
5002 else if (pbEncoded[0] == ASN_GENERALTIME)
5003 decode = CRYPT_AsnDecodeGeneralizedTime;
5004 if (decode)
5005 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
5006 pcbStructInfo, pcbDecoded);
5007 else
5009 SetLastError(CRYPT_E_ASN1_BADTAG);
5010 ret = FALSE;
5012 return ret;
5015 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
5016 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5017 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5019 BOOL ret;
5021 __TRY
5023 DWORD bytesNeeded = 0;
5025 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
5026 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
5027 if (ret)
5029 if (!pvStructInfo)
5030 *pcbStructInfo = bytesNeeded;
5031 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5032 pvStructInfo, pcbStructInfo, bytesNeeded)))
5034 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5035 pvStructInfo = *(BYTE **)pvStructInfo;
5036 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
5037 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5038 &bytesNeeded, NULL);
5039 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5040 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
5044 __EXCEPT_PAGE_FAULT
5046 SetLastError(STATUS_ACCESS_VIOLATION);
5047 ret = FALSE;
5049 __ENDTRY
5050 return ret;
5053 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
5054 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5055 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5057 BOOL ret = TRUE;
5059 __TRY
5061 if (pbEncoded[0] == ASN_SEQUENCEOF)
5063 DWORD bytesNeeded, dataLen, remainingLen, cValue;
5065 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5067 BYTE lenBytes;
5068 const BYTE *ptr;
5070 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5071 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
5072 cValue = 0;
5073 ptr = pbEncoded + 1 + lenBytes;
5074 remainingLen = dataLen;
5075 while (ret && remainingLen)
5077 DWORD nextLen;
5079 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5080 if (ret)
5082 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5084 remainingLen -= 1 + nextLenBytes + nextLen;
5085 ptr += 1 + nextLenBytes + nextLen;
5086 bytesNeeded += sizeof(CRYPT_DER_BLOB);
5087 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
5088 bytesNeeded += 1 + nextLenBytes + nextLen;
5089 cValue++;
5092 if (ret)
5094 CRYPT_SEQUENCE_OF_ANY *seq;
5095 BYTE *nextPtr;
5096 DWORD i;
5098 if (!pvStructInfo)
5099 *pcbStructInfo = bytesNeeded;
5100 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5101 pvStructInfo, pcbStructInfo, bytesNeeded)))
5103 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5104 pvStructInfo = *(BYTE **)pvStructInfo;
5105 seq = pvStructInfo;
5106 seq->cValue = cValue;
5107 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
5108 sizeof(*seq));
5109 nextPtr = (BYTE *)seq->rgValue +
5110 cValue * sizeof(CRYPT_DER_BLOB);
5111 ptr = pbEncoded + 1 + lenBytes;
5112 remainingLen = dataLen;
5113 i = 0;
5114 while (ret && remainingLen)
5116 DWORD nextLen;
5118 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5119 if (ret)
5121 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5123 seq->rgValue[i].cbData = 1 + nextLenBytes +
5124 nextLen;
5125 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
5126 seq->rgValue[i].pbData = (BYTE *)ptr;
5127 else
5129 seq->rgValue[i].pbData = nextPtr;
5130 memcpy(nextPtr, ptr, 1 + nextLenBytes +
5131 nextLen);
5132 nextPtr += 1 + nextLenBytes + nextLen;
5134 remainingLen -= 1 + nextLenBytes + nextLen;
5135 ptr += 1 + nextLenBytes + nextLen;
5136 i++;
5139 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5140 CRYPT_FreeSpace(pDecodePara, seq);
5145 else
5147 SetLastError(CRYPT_E_ASN1_BADTAG);
5148 ret = FALSE;
5151 __EXCEPT_PAGE_FAULT
5153 SetLastError(STATUS_ACCESS_VIOLATION);
5154 ret = FALSE;
5156 __ENDTRY
5157 return ret;
5160 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
5161 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5162 DWORD *pcbDecoded)
5164 BOOL ret;
5166 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
5168 DWORD bytesNeeded = 0, dataLen;
5170 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5172 struct AsnArrayDescriptor arrayDesc = {
5173 ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5174 offsetof(CRL_DIST_POINT_NAME, u.FullName.cAltEntry),
5175 offsetof(CRL_DIST_POINT_NAME, u.FullName.rgAltEntry),
5176 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u),
5177 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
5178 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
5179 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5180 DWORD nameLen;
5182 if (dataLen)
5184 ret = CRYPT_AsnDecodeArray(&arrayDesc,
5185 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
5186 dwFlags, NULL, NULL, &nameLen, NULL);
5187 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
5188 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u);
5190 else
5191 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
5192 if (pcbDecoded)
5193 *pcbDecoded = 1 + lenBytes + dataLen;
5194 if (!pvStructInfo)
5195 *pcbStructInfo = bytesNeeded;
5196 else if (*pcbStructInfo < bytesNeeded)
5198 *pcbStructInfo = bytesNeeded;
5199 SetLastError(ERROR_MORE_DATA);
5200 ret = FALSE;
5202 else
5204 CRL_DIST_POINT_NAME *name = pvStructInfo;
5206 *pcbStructInfo = bytesNeeded;
5207 if (dataLen)
5209 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
5210 ret = CRYPT_AsnDecodeArray(&arrayDesc,
5211 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
5212 dwFlags, NULL, &name->u.FullName.cAltEntry, &nameLen,
5213 NULL);
5215 else
5216 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
5220 else
5222 SetLastError(CRYPT_E_ASN1_BADTAG);
5223 ret = FALSE;
5225 return ret;
5228 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
5229 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5231 struct AsnDecodeSequenceItem items[] = {
5232 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
5233 DistPointName), CRYPT_AsnDecodeDistPointName,
5234 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
5235 DistPointName.u.FullName.rgAltEntry), 0 },
5236 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
5237 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
5238 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
5239 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
5240 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
5241 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
5243 CRL_DIST_POINT *point = pvStructInfo;
5244 BOOL ret;
5246 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5247 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5248 pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
5249 return ret;
5252 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
5253 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5254 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5256 BOOL ret;
5258 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5259 pDecodePara, pvStructInfo, *pcbStructInfo);
5261 __TRY
5263 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5264 offsetof(CRL_DIST_POINTS_INFO, cDistPoint),
5265 offsetof(CRL_DIST_POINTS_INFO, rgDistPoint),
5266 sizeof(CRL_DIST_POINTS_INFO),
5267 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
5268 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
5269 CRL_DIST_POINTS_INFO *info = pvStructInfo;
5271 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5272 info->rgDistPoint = (CRL_DIST_POINT *)(info + 1);
5273 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5274 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
5276 __EXCEPT_PAGE_FAULT
5278 SetLastError(STATUS_ACCESS_VIOLATION);
5279 ret = FALSE;
5281 __ENDTRY
5282 return ret;
5285 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
5286 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5287 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5289 BOOL ret;
5291 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5292 pDecodePara, pvStructInfo, *pcbStructInfo);
5294 __TRY
5296 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5297 offsetof(CERT_ENHKEY_USAGE, cUsageIdentifier),
5298 offsetof(CERT_ENHKEY_USAGE, rgpszUsageIdentifier),
5299 sizeof(CERT_ENHKEY_USAGE),
5300 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
5301 CERT_ENHKEY_USAGE *usage = pvStructInfo;
5303 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5304 usage->rgpszUsageIdentifier = (LPSTR *)(usage + 1);
5305 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5306 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
5308 __EXCEPT_PAGE_FAULT
5310 SetLastError(STATUS_ACCESS_VIOLATION);
5311 ret = FALSE;
5313 __ENDTRY
5314 return ret;
5317 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
5318 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5319 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5321 BOOL ret;
5323 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5324 pDecodePara, pvStructInfo, *pcbStructInfo);
5326 __TRY
5328 struct AsnDecodeSequenceItem items[] = {
5329 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
5330 DistPointName), CRYPT_AsnDecodeDistPointName,
5331 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
5332 offsetof(CRL_ISSUING_DIST_POINT,
5333 DistPointName.u.FullName.rgAltEntry), 0 },
5334 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
5335 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5336 FALSE, 0 },
5337 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
5338 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5339 FALSE, 0 },
5340 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
5341 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
5342 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
5343 OnlySomeReasonFlags.pbData), 0 },
5344 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
5345 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
5348 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5349 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5350 pcbStructInfo, NULL, NULL);
5352 __EXCEPT_PAGE_FAULT
5354 SetLastError(STATUS_ACCESS_VIOLATION);
5355 ret = FALSE;
5357 __ENDTRY
5358 return ret;
5361 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
5362 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5363 DWORD *pcbDecoded)
5365 BOOL ret;
5366 DWORD max, size = sizeof(max);
5368 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5369 pvStructInfo, *pcbStructInfo, pcbDecoded);
5371 if (!cbEncoded)
5373 SetLastError(CRYPT_E_ASN1_EOD);
5374 return FALSE;
5376 if (pbEncoded[0] != (ASN_CONTEXT | 1))
5378 SetLastError(CRYPT_E_ASN1_BADTAG);
5379 return FALSE;
5381 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
5382 &max, &size, pcbDecoded)))
5384 DWORD bytesNeeded = FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum);
5386 if (!pvStructInfo)
5387 *pcbStructInfo = bytesNeeded;
5388 else if (*pcbStructInfo < bytesNeeded)
5390 *pcbStructInfo = bytesNeeded;
5391 SetLastError(ERROR_MORE_DATA);
5392 ret = FALSE;
5394 else
5396 CERT_GENERAL_SUBTREE *subtree = CONTAINING_RECORD(pvStructInfo,
5397 CERT_GENERAL_SUBTREE, fMaximum);
5399 *pcbStructInfo = bytesNeeded;
5400 /* The BOOL is implicit: if the integer is present, then it's
5401 * TRUE.
5403 subtree->fMaximum = TRUE;
5404 subtree->dwMaximum = max;
5407 TRACE("returning %d\n", ret);
5408 return ret;
5411 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
5412 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5413 DWORD *pcbDecoded)
5415 BOOL ret;
5416 struct AsnDecodeSequenceItem items[] = {
5417 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
5418 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
5419 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
5420 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
5421 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
5422 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
5423 CRYPT_AsnDecodeMaximum, FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum),
5424 TRUE, FALSE, 0, 0 },
5426 CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
5428 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5429 pvStructInfo, *pcbStructInfo, pcbDecoded);
5431 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5432 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5433 pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
5434 if (pcbDecoded)
5436 TRACE("%d\n", *pcbDecoded);
5437 if (*pcbDecoded < cbEncoded)
5438 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
5439 *(pbEncoded + *pcbDecoded + 1));
5441 TRACE("returning %d\n", ret);
5442 return ret;
5445 static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
5446 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5447 DWORD *pcbDecoded)
5449 BOOL ret = TRUE;
5450 struct AsnArrayDescriptor arrayDesc = { 0,
5451 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5452 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree),
5453 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5454 cExcludedSubtree),
5455 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5456 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5458 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5459 pvStructInfo, *pcbStructInfo, pcbDecoded);
5461 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5462 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5463 return ret;
5466 static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
5467 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5468 DWORD *pcbDecoded)
5470 BOOL ret = TRUE;
5471 struct AsnArrayDescriptor arrayDesc = { 0,
5472 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5473 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree),
5474 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5475 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5476 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5478 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5479 pvStructInfo, *pcbStructInfo, pcbDecoded);
5481 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5482 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5483 return ret;
5486 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
5487 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5488 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5490 BOOL ret = FALSE;
5492 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5493 pDecodePara, pvStructInfo, *pcbStructInfo);
5495 __TRY
5497 struct AsnDecodeSequenceItem items[] = {
5498 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5499 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5500 CRYPT_AsnDecodePermittedSubtree,
5501 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5502 cExcludedSubtree), TRUE, TRUE,
5503 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
5504 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
5505 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5506 CRYPT_AsnDecodeExcludedSubtree,
5507 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5508 TRUE, TRUE,
5509 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
5512 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5513 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5514 pcbStructInfo, NULL, NULL);
5516 __EXCEPT_PAGE_FAULT
5518 SetLastError(STATUS_ACCESS_VIOLATION);
5520 __ENDTRY
5521 return ret;
5524 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
5525 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5526 DWORD *pcbDecoded)
5528 BOOL ret;
5529 struct AsnDecodeSequenceItem items[] = {
5530 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
5531 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
5532 Issuer.pbData) },
5533 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
5534 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
5535 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
5537 CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
5539 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5540 pvStructInfo, *pcbStructInfo, pcbDecoded);
5542 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5543 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5544 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
5545 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
5547 SetLastError(CRYPT_E_ASN1_CORRUPT);
5548 ret = FALSE;
5550 TRACE("returning %d\n", ret);
5551 return ret;
5554 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
5555 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5556 DWORD *pcbDecoded)
5558 CMSG_SIGNER_INFO *info = pvStructInfo;
5559 struct AsnDecodeSequenceItem items[] = {
5560 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
5561 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5562 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
5563 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
5564 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
5565 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
5566 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5567 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5568 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5569 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
5570 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5571 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5572 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
5573 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5574 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
5575 HashEncryptionAlgorithm.pszObjId), 0 },
5576 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
5577 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
5578 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
5579 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5580 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
5581 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5582 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5584 BOOL ret;
5586 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5587 pvStructInfo, *pcbStructInfo);
5589 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5590 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5591 pcbDecoded, info ? info->Issuer.pbData : NULL);
5592 return ret;
5595 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
5596 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5597 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5599 BOOL ret = FALSE;
5601 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5602 pDecodePara, pvStructInfo, *pcbStructInfo);
5604 __TRY
5606 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
5607 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5608 if (ret && pvStructInfo)
5610 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5611 pcbStructInfo, *pcbStructInfo);
5612 if (ret)
5614 CMSG_SIGNER_INFO *info;
5616 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5617 pvStructInfo = *(BYTE **)pvStructInfo;
5618 info = pvStructInfo;
5619 info->Issuer.pbData = ((BYTE *)info +
5620 sizeof(CMSG_SIGNER_INFO));
5621 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
5622 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5623 pcbStructInfo, NULL);
5624 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5625 CRYPT_FreeSpace(pDecodePara, info);
5629 __EXCEPT_PAGE_FAULT
5631 SetLastError(STATUS_ACCESS_VIOLATION);
5633 __ENDTRY
5634 TRACE("returning %d\n", ret);
5635 return ret;
5638 static BOOL verify_and_copy_certificate(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5639 void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5641 PCCERT_CONTEXT cert;
5643 cert = CertCreateCertificateContext(X509_ASN_ENCODING, pbEncoded, cbEncoded);
5644 if (!cert)
5646 WARN("CertCreateCertificateContext error %#x\n", GetLastError());
5647 *pcbStructInfo = 0;
5648 *pcbDecoded = 0;
5649 return TRUE;
5652 CertFreeCertificateContext(cert);
5654 return CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, pcbDecoded);
5657 static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
5658 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5659 DWORD *pcbDecoded)
5661 BOOL ret;
5662 struct AsnArrayDescriptor arrayDesc = { 0,
5663 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
5664 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded),
5665 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded),
5666 verify_and_copy_certificate,
5667 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5669 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5670 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5672 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5673 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5674 return ret;
5677 static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
5678 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5679 DWORD *pcbDecoded)
5681 BOOL ret;
5682 struct AsnArrayDescriptor arrayDesc = { 0,
5683 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded),
5684 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded),
5685 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content),
5686 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB),
5687 TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5689 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5690 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5692 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5693 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5694 return ret;
5697 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
5698 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5699 DWORD *pcbDecoded)
5701 CERT_ID *id = pvStructInfo;
5702 BOOL ret = FALSE;
5704 if (*pbEncoded == ASN_SEQUENCEOF)
5706 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
5707 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
5708 if (ret)
5710 if (id)
5711 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5712 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
5713 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5714 sizeof(CERT_ISSUER_SERIAL_NUMBER);
5715 else
5716 *pcbStructInfo = sizeof(CERT_ID);
5719 else if (*pbEncoded == (ASN_CONTEXT | 0))
5721 ret = CRYPT_AsnDecodeOctets(pbEncoded, cbEncoded, dwFlags,
5722 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
5723 if (ret)
5725 if (id)
5726 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
5727 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
5728 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5729 sizeof(CRYPT_DATA_BLOB);
5730 else
5731 *pcbStructInfo = sizeof(CERT_ID);
5734 else
5735 SetLastError(CRYPT_E_ASN1_BADTAG);
5736 return ret;
5739 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5740 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5741 DWORD *pcbDecoded)
5743 CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
5744 struct AsnDecodeSequenceItem items[] = {
5745 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5746 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5747 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5748 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5749 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
5750 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5751 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5752 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5753 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5754 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5755 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5756 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5757 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5758 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5759 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5760 HashEncryptionAlgorithm.pszObjId), 0 },
5761 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5762 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
5763 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5764 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5765 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5766 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5767 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5769 BOOL ret;
5771 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5772 pvStructInfo, *pcbStructInfo);
5774 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5775 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5776 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
5777 return ret;
5780 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5781 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5782 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5784 BOOL ret = FALSE;
5786 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5787 pDecodePara, pvStructInfo, *pcbStructInfo);
5789 __TRY
5791 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5792 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5793 if (ret && pvStructInfo)
5795 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5796 pcbStructInfo, *pcbStructInfo);
5797 if (ret)
5799 CMSG_CMS_SIGNER_INFO *info;
5801 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5802 pvStructInfo = *(BYTE **)pvStructInfo;
5803 info = pvStructInfo;
5804 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
5805 sizeof(CMSG_CMS_SIGNER_INFO));
5806 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5807 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5808 pcbStructInfo, NULL);
5809 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5810 CRYPT_FreeSpace(pDecodePara, info);
5814 __EXCEPT_PAGE_FAULT
5816 SetLastError(STATUS_ACCESS_VIOLATION);
5818 __ENDTRY
5819 TRACE("returning %d\n", ret);
5820 return ret;
5823 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5824 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5826 BOOL ret;
5827 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5828 offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5829 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo),
5830 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo),
5831 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5832 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
5834 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5835 pvStructInfo, *pcbStructInfo, pcbDecoded);
5837 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5838 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5839 return ret;
5842 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5843 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5844 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5846 BOOL ret = FALSE;
5847 struct AsnDecodeSequenceItem items[] = {
5848 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5849 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5850 /* Placeholder for the hash algorithms - redundant with those in the
5851 * signers, so just ignore them.
5853 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5854 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5855 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5856 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5857 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5858 offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
5859 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
5860 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5861 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5862 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
5863 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
5864 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5865 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5866 CRYPT_DecodeSignerArray,
5867 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE,
5868 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5871 TRACE("%p, %d, %08x, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags,
5872 pDecodePara, signedInfo, pcbSignedInfo);
5874 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5875 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5876 NULL, NULL);
5877 TRACE("returning %d\n", ret);
5878 return ret;
5881 static BOOL CRYPT_AsnDecodeRecipientInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5882 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5884 BOOL ret;
5885 CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
5886 struct AsnDecodeSequenceItem items[] = {
5887 { ASN_INTEGER, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, dwVersion),
5888 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5889 { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5890 RecipientId.u.IssuerSerialNumber), CRYPT_AsnDecodeIssuerSerialNumber,
5891 sizeof(CERT_ISSUER_SERIAL_NUMBER), FALSE, TRUE,
5892 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5893 RecipientId.u.IssuerSerialNumber.Issuer.pbData), 0 },
5894 { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5895 KeyEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
5896 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
5897 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5898 KeyEncryptionAlgorithm.pszObjId), 0 },
5899 { ASN_OCTETSTRING, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey),
5900 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
5901 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey.pbData), 0 },
5904 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5905 pvStructInfo, *pcbStructInfo, pcbDecoded);
5907 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5908 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5909 pcbDecoded, info ? info->RecipientId.u.IssuerSerialNumber.Issuer.pbData :
5910 NULL);
5911 if (info)
5912 info->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5913 TRACE("returning %d\n", ret);
5914 return ret;
5917 static BOOL CRYPT_DecodeRecipientInfoArray(const BYTE *pbEncoded,
5918 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5919 DWORD *pcbDecoded)
5921 BOOL ret;
5922 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5923 offsetof(CRYPT_ENVELOPED_DATA, cRecipientInfo),
5924 offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo),
5925 MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
5926 CRYPT_AsnDecodeRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), TRUE,
5927 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5928 RecipientId.u.IssuerSerialNumber.Issuer.pbData) };
5930 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5931 pvStructInfo, *pcbStructInfo, pcbDecoded);
5933 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5934 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5935 TRACE("returning %d\n", ret);
5936 return ret;
5939 static BOOL CRYPT_AsnDecodeEncryptedContentInfo(const BYTE *pbEncoded,
5940 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5941 DWORD *pcbDecoded)
5943 BOOL ret;
5944 CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
5945 struct AsnDecodeSequenceItem items[] = {
5946 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5947 contentType), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
5948 FALSE, TRUE, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5949 contentType), 0 },
5950 { ASN_SEQUENCEOF, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5951 contentEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
5952 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
5953 offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5954 contentEncryptionAlgorithm.pszObjId), 0 },
5955 { ASN_CONTEXT | 0, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5956 encryptedContent), CRYPT_AsnDecodeOctets,
5957 sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
5958 offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, encryptedContent.pbData) },
5961 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5962 pvStructInfo, *pcbStructInfo, pcbDecoded);
5964 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5965 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5966 pcbDecoded, info ? info->contentType : NULL);
5967 TRACE("returning %d\n", ret);
5968 return ret;
5971 BOOL CRYPT_AsnDecodePKCSEnvelopedData(const BYTE *pbEncoded, DWORD cbEncoded,
5972 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5973 CRYPT_ENVELOPED_DATA *envelopedData, DWORD *pcbEnvelopedData)
5975 BOOL ret;
5976 struct AsnDecodeSequenceItem items[] = {
5977 { ASN_INTEGER, offsetof(CRYPT_ENVELOPED_DATA, version),
5978 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5979 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ENVELOPED_DATA,
5980 cRecipientInfo), CRYPT_DecodeRecipientInfoArray,
5981 MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
5982 FALSE, TRUE, offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo), 0 },
5983 { ASN_SEQUENCEOF, offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo),
5984 CRYPT_AsnDecodeEncryptedContentInfo,
5985 sizeof(CRYPT_ENCRYPTED_CONTENT_INFO), FALSE, TRUE,
5986 offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo.contentType), 0 },
5989 TRACE("%p, %d, %08x, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags,
5990 pDecodePara, envelopedData, pcbEnvelopedData);
5992 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5993 pbEncoded, cbEncoded, dwFlags, pDecodePara, envelopedData,
5994 pcbEnvelopedData, NULL, NULL);
5995 TRACE("returning %d\n", ret);
5996 return ret;
5999 static BOOL WINAPI CRYPT_AsnDecodeObjectIdentifier(DWORD dwCertEncodingType,
6000 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6001 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6003 DWORD bytesNeeded = 0;
6004 BOOL ret;
6006 __TRY
6008 ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
6009 NULL, &bytesNeeded, NULL);
6010 if (ret)
6012 if (!pvStructInfo)
6013 *pcbStructInfo = bytesNeeded;
6014 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
6016 LPSTR *info;
6018 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6019 pvStructInfo = *(BYTE **)pvStructInfo;
6021 info = pvStructInfo;
6022 *info = (void *)((BYTE *)info + sizeof(*info));
6023 ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
6024 pvStructInfo, &bytesNeeded, NULL);
6025 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
6026 CRYPT_FreeSpace(pDecodePara, info);
6030 __EXCEPT_PAGE_FAULT
6032 SetLastError(STATUS_ACCESS_VIOLATION);
6033 ret = FALSE;
6035 __ENDTRY
6036 return ret;
6039 static BOOL WINAPI CRYPT_AsnDecodeEccSignature(DWORD dwCertEncodingType,
6040 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6041 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6043 BOOL ret;
6044 struct AsnDecodeSequenceItem items[] = {
6045 { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, r),
6046 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE,
6047 TRUE, offsetof(CERT_ECC_SIGNATURE, r.pbData), 0 },
6048 { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, s),
6049 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE,
6050 TRUE, offsetof(CERT_ECC_SIGNATURE, s.pbData), 0 },
6053 __TRY
6055 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6056 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6057 pcbStructInfo, NULL, NULL);
6059 __EXCEPT_PAGE_FAULT
6061 SetLastError(STATUS_ACCESS_VIOLATION);
6062 ret = FALSE;
6064 __ENDTRY
6065 return ret;
6068 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
6069 LPCSTR lpszStructType)
6071 CryptDecodeObjectExFunc decodeFunc = NULL;
6073 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
6074 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
6076 SetLastError(ERROR_FILE_NOT_FOUND);
6077 return NULL;
6079 if (IS_INTOID(lpszStructType))
6081 switch (LOWORD(lpszStructType))
6083 case LOWORD(X509_CERT):
6084 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
6085 break;
6086 case LOWORD(X509_CERT_TO_BE_SIGNED):
6087 decodeFunc = CRYPT_AsnDecodeCert;
6088 break;
6089 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
6090 decodeFunc = CRYPT_AsnDecodeCRL;
6091 break;
6092 case LOWORD(X509_EXTENSIONS):
6093 decodeFunc = CRYPT_AsnDecodeExtensions;
6094 break;
6095 case LOWORD(X509_NAME_VALUE):
6096 decodeFunc = CRYPT_AsnDecodeNameValue;
6097 break;
6098 case LOWORD(X509_NAME):
6099 decodeFunc = CRYPT_AsnDecodeName;
6100 break;
6101 case LOWORD(X509_PUBLIC_KEY_INFO):
6102 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
6103 break;
6104 case LOWORD(X509_AUTHORITY_KEY_ID):
6105 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
6106 break;
6107 case LOWORD(X509_ALTERNATE_NAME):
6108 decodeFunc = CRYPT_AsnDecodeAltName;
6109 break;
6110 case LOWORD(X509_BASIC_CONSTRAINTS):
6111 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
6112 break;
6113 case LOWORD(X509_BASIC_CONSTRAINTS2):
6114 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
6115 break;
6116 case LOWORD(X509_CERT_POLICIES):
6117 decodeFunc = CRYPT_AsnDecodeCertPolicies;
6118 break;
6119 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
6120 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
6121 break;
6122 case LOWORD(PKCS_RSA_PRIVATE_KEY):
6123 decodeFunc = CRYPT_AsnDecodeRsaPrivKey;
6124 break;
6125 case LOWORD(X509_UNICODE_NAME):
6126 decodeFunc = CRYPT_AsnDecodeUnicodeName;
6127 break;
6128 case LOWORD(PKCS_ATTRIBUTE):
6129 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
6130 break;
6131 case LOWORD(X509_UNICODE_NAME_VALUE):
6132 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
6133 break;
6134 case LOWORD(X509_OCTET_STRING):
6135 decodeFunc = CRYPT_AsnDecodeOctetString;
6136 break;
6137 case LOWORD(X509_BITS):
6138 case LOWORD(X509_KEY_USAGE):
6139 decodeFunc = CRYPT_AsnDecodeBits;
6140 break;
6141 case LOWORD(X509_INTEGER):
6142 decodeFunc = CRYPT_AsnDecodeInt;
6143 break;
6144 case LOWORD(X509_MULTI_BYTE_INTEGER):
6145 decodeFunc = CRYPT_AsnDecodeInteger;
6146 break;
6147 case LOWORD(X509_MULTI_BYTE_UINT):
6148 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
6149 break;
6150 case LOWORD(X509_ENUMERATED):
6151 decodeFunc = CRYPT_AsnDecodeEnumerated;
6152 break;
6153 case LOWORD(X509_CHOICE_OF_TIME):
6154 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
6155 break;
6156 case LOWORD(X509_AUTHORITY_KEY_ID2):
6157 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
6158 break;
6159 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
6160 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
6161 break;
6162 case LOWORD(PKCS_CONTENT_INFO):
6163 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
6164 break;
6165 case LOWORD(X509_SEQUENCE_OF_ANY):
6166 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
6167 break;
6168 case LOWORD(PKCS_UTC_TIME):
6169 decodeFunc = CRYPT_AsnDecodeUtcTime;
6170 break;
6171 case LOWORD(X509_CRL_DIST_POINTS):
6172 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
6173 break;
6174 case LOWORD(X509_ENHANCED_KEY_USAGE):
6175 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
6176 break;
6177 case LOWORD(PKCS_CTL):
6178 decodeFunc = CRYPT_AsnDecodeCTL;
6179 break;
6180 case LOWORD(PKCS_SMIME_CAPABILITIES):
6181 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
6182 break;
6183 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
6184 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
6185 break;
6186 case LOWORD(PKCS_ATTRIBUTES):
6187 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
6188 break;
6189 case LOWORD(X509_ISSUING_DIST_POINT):
6190 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
6191 break;
6192 case LOWORD(X509_NAME_CONSTRAINTS):
6193 decodeFunc = CRYPT_AsnDecodeNameConstraints;
6194 break;
6195 case LOWORD(X509_POLICY_MAPPINGS):
6196 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6197 break;
6198 case LOWORD(X509_POLICY_CONSTRAINTS):
6199 decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
6200 break;
6201 case LOWORD(PKCS7_SIGNER_INFO):
6202 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
6203 break;
6204 case LOWORD(CMS_SIGNER_INFO):
6205 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
6206 break;
6207 case LOWORD(X509_OBJECT_IDENTIFIER):
6208 decodeFunc = CRYPT_AsnDecodeObjectIdentifier;
6209 break;
6210 case LOWORD(X509_ECC_SIGNATURE):
6211 decodeFunc = CRYPT_AsnDecodeEccSignature;
6212 break;
6215 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
6216 decodeFunc = CRYPT_AsnDecodeExtensions;
6217 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
6218 decodeFunc = CRYPT_AsnDecodeUtcTime;
6219 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
6220 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
6221 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
6222 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
6223 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
6224 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6225 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
6226 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
6227 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
6228 decodeFunc = CRYPT_AsnDecodeEnumerated;
6229 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
6230 decodeFunc = CRYPT_AsnDecodeBits;
6231 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
6232 decodeFunc = CRYPT_AsnDecodeOctetString;
6233 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
6234 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
6235 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
6236 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
6237 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
6238 decodeFunc = CRYPT_AsnDecodeAltName;
6239 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
6240 decodeFunc = CRYPT_AsnDecodeAltName;
6241 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
6242 decodeFunc = CRYPT_AsnDecodeAltName;
6243 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
6244 decodeFunc = CRYPT_AsnDecodeAltName;
6245 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
6246 decodeFunc = CRYPT_AsnDecodeAltName;
6247 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
6248 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
6249 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
6250 decodeFunc = CRYPT_AsnDecodeCertPolicies;
6251 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
6252 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6253 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
6254 decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
6255 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
6256 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
6257 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
6258 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
6259 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
6260 decodeFunc = CRYPT_AsnDecodeNameConstraints;
6261 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
6262 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
6263 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
6264 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
6265 else if (!strcmp(lpszStructType, szOID_CTL))
6266 decodeFunc = CRYPT_AsnDecodeCTL;
6267 else if (!strcmp(lpszStructType, szOID_ECC_PUBLIC_KEY))
6268 decodeFunc = CRYPT_AsnDecodeObjectIdentifier;
6269 return decodeFunc;
6272 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
6273 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
6275 static HCRYPTOIDFUNCSET set = NULL;
6276 CryptDecodeObjectFunc decodeFunc = NULL;
6278 if (!set)
6279 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
6280 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
6281 (void **)&decodeFunc, hFunc);
6282 return decodeFunc;
6285 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
6286 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
6288 static HCRYPTOIDFUNCSET set = NULL;
6289 CryptDecodeObjectExFunc decodeFunc = NULL;
6291 if (!set)
6292 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
6293 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
6294 (void **)&decodeFunc, hFunc);
6295 return decodeFunc;
6298 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
6299 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
6300 DWORD *pcbStructInfo)
6302 return CryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
6303 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
6306 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
6307 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6308 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6310 BOOL ret = FALSE;
6311 CryptDecodeObjectExFunc decodeFunc;
6312 HCRYPTOIDFUNCADDR hFunc = NULL;
6314 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
6315 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
6316 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
6318 if (!pvStructInfo && !pcbStructInfo)
6320 SetLastError(ERROR_INVALID_PARAMETER);
6321 return FALSE;
6323 if (cbEncoded > MAX_ENCODED_LEN)
6325 SetLastError(CRYPT_E_ASN1_LARGE);
6326 return FALSE;
6329 SetLastError(NOERROR);
6330 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6332 if (!pvStructInfo)
6334 SetLastError(ERROR_INVALID_PARAMETER);
6335 return FALSE;
6337 *(BYTE **)pvStructInfo = NULL;
6339 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
6340 if (!decodeFunc)
6342 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
6343 debugstr_a(lpszStructType));
6344 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
6345 &hFunc);
6347 if (decodeFunc)
6348 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
6349 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
6350 else
6352 CryptDecodeObjectFunc pCryptDecodeObject =
6353 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
6355 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
6356 * directly, as that could cause an infinite loop.
6358 if (pCryptDecodeObject)
6360 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6362 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
6363 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
6364 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
6365 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
6367 ret = pCryptDecodeObject(dwCertEncodingType,
6368 lpszStructType, pbEncoded, cbEncoded, dwFlags,
6369 *(BYTE **)pvStructInfo, pcbStructInfo);
6370 if (!ret)
6371 CRYPT_FreeSpace(pDecodePara, *(BYTE **)pvStructInfo);
6374 else
6375 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
6376 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
6379 if (hFunc)
6380 CryptFreeOIDFunctionAddress(hFunc, 0);
6381 TRACE_(crypt)("returning %d\n", ret);
6382 return ret;
6385 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
6387 BOOL ret;
6389 TRACE_(crypt)("(%p)\n", pPFX);
6391 /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
6392 * version integer of length 1 (3 encoded byes) and at least one other
6393 * datum (two encoded bytes), plus at least two bytes for the outer
6394 * sequence. Thus, even an empty PFX blob is at least 7 bytes in length.
6396 if (pPFX->cbData < 7)
6397 ret = FALSE;
6398 else if (pPFX->pbData[0] == ASN_SEQUENCE)
6400 DWORD len;
6402 if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
6404 BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
6406 /* Need at least three bytes for the integer version */
6407 if (pPFX->cbData < 1 + lenLen + 3)
6408 ret = FALSE;
6409 else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
6410 pPFX->pbData[1 + lenLen + 1] != 1 || /* Definite length */
6411 pPFX->pbData[1 + lenLen + 2] != 3) /* PFX version */
6412 ret = FALSE;
6415 else
6416 ret = FALSE;
6417 return ret;