crypt32: Correct GET_LEN_BYTES for the indefinite-length form.
[wine/gsoc_dplay.git] / dlls / crypt32 / decode.c
blobef95a3488efa10866dff1a965cc688a3d2551f91
1 /*
2 * Copyright 2005-2007 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 <assert.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
38 #define NONAMELESSUNION
40 #include "windef.h"
41 #include "winbase.h"
42 #include "wincrypt.h"
43 #include "winnls.h"
44 #include "snmp.h"
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "crypt32_private.h"
49 /* This is a bit arbitrary, but to set some limit: */
50 #define MAX_ENCODED_LEN 0x02000000
52 #define ASN_FLAGS_MASK 0xe0
53 #define ASN_TYPE_MASK 0x1f
55 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
56 WINE_DECLARE_DEBUG_CHANNEL(crypt);
58 struct GenericArray
60 DWORD cItems;
61 BYTE *rgItems;
64 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
65 DWORD, DWORD, void *, DWORD *);
66 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
67 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
69 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
70 * The dwCertEncodingType and lpszStructType are ignored by the built-in
71 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
72 * since it must call functions in external DLLs that follow these signatures.
74 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
75 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
76 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
77 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
78 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
79 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
80 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
81 * time, doesn't do memory allocation, and doesn't do exception handling.
82 * (This isn't intended to be the externally-called one.)
84 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
86 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
87 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
88 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
89 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
90 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
91 /* Internal function */
92 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
93 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
94 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
97 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
98 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
99 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
100 * member has been initialized, doesn't do exception handling, and doesn't do
101 * memory allocation.
103 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
104 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
105 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
106 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
107 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
108 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
109 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
110 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
111 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
112 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
113 * member has been initialized, doesn't do exception handling, and doesn't do
114 * memory allocation. Also doesn't check tag, assumes the caller has checked
115 * it.
117 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
118 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
119 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
120 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
121 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
122 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
123 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
124 void *pvStructInfo, DWORD *pcbStructInfo);
126 /* Gets the number of length bytes from the given (leading) length byte */
127 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
129 /* Helper function to get the encoded length of the data starting at pbEncoded,
130 * where pbEncoded[0] is the tag. If the data are too short to contain a
131 * length or if the length is too large for cbEncoded, sets an appropriate
132 * error code and returns FALSE.
134 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
135 DWORD *len)
137 BOOL ret;
139 if (cbEncoded <= 1)
141 SetLastError(CRYPT_E_ASN1_CORRUPT);
142 ret = FALSE;
144 else if (pbEncoded[1] <= 0x7f)
146 if (pbEncoded[1] + 1 > cbEncoded)
148 SetLastError(CRYPT_E_ASN1_EOD);
149 ret = FALSE;
151 else
153 *len = pbEncoded[1];
154 ret = TRUE;
157 else if (pbEncoded[1] == 0x80)
159 FIXME("unimplemented for indefinite-length encoding\n");
160 SetLastError(CRYPT_E_ASN1_CORRUPT);
161 ret = FALSE;
163 else
165 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
167 if (lenLen > sizeof(DWORD) + 1)
169 SetLastError(CRYPT_E_ASN1_LARGE);
170 ret = FALSE;
172 else if (lenLen + 2 > cbEncoded)
174 SetLastError(CRYPT_E_ASN1_CORRUPT);
175 ret = FALSE;
177 else
179 DWORD out = 0;
181 pbEncoded += 2;
182 while (--lenLen)
184 out <<= 8;
185 out |= *pbEncoded++;
187 if (out + lenLen + 1 > cbEncoded)
189 SetLastError(CRYPT_E_ASN1_EOD);
190 ret = FALSE;
192 else
194 *len = out;
195 ret = TRUE;
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 PCRYPT_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(0, 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 return ret;
233 /* tag:
234 * The expected tag of the item. If tag is 0, decodeFunc is called
235 * regardless of the tag value seen.
236 * offset:
237 * A sequence is decoded into a struct. The offset member is the
238 * offset of this item within that struct.
239 * decodeFunc:
240 * The decoder function to use. If this is NULL, then the member isn't
241 * decoded, but minSize space is reserved for it.
242 * minSize:
243 * The minimum amount of space occupied after decoding. You must set this.
244 * optional:
245 * If true, and the tag doesn't match the expected tag for this item,
246 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
247 * filled with 0 for this member.
248 * hasPointer, pointerOffset:
249 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
250 * the offset within the struct of the data pointer (or to the
251 * first data pointer, if more than one exist).
252 * size:
253 * Used by CRYPT_AsnDecodeSequence, not for your use.
255 struct AsnDecodeSequenceItem
257 BYTE tag;
258 DWORD offset;
259 CryptDecodeObjectExFunc decodeFunc;
260 DWORD minSize;
261 BOOL optional;
262 BOOL hasPointer;
263 DWORD pointerOffset;
264 DWORD size;
267 /* Decodes the items in a sequence, where the items are described in items,
268 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
269 * pvStructInfo. nextData is a pointer to the memory location at which the
270 * first decoded item with a dynamic pointer should point.
271 * Upon decoding, *cbDecoded is the total number of bytes decoded.
273 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
274 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
275 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
276 DWORD *cbDecoded)
278 BOOL ret;
279 DWORD i, decoded = 0;
280 const BYTE *ptr = pbEncoded;
282 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
283 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
285 for (i = 0, ret = TRUE; ret && i < cItem; i++)
287 if (cbEncoded - (ptr - pbEncoded) != 0)
289 DWORD nextItemLen;
291 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
292 &nextItemLen)))
294 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
296 if (ptr[0] == items[i].tag || !items[i].tag)
298 if (nextData && pvStructInfo && items[i].hasPointer)
300 TRACE("Setting next pointer to %p\n",
301 nextData);
302 *(BYTE **)((BYTE *)pvStructInfo +
303 items[i].pointerOffset) = nextData;
305 if (items[i].decodeFunc)
307 if (pvStructInfo)
308 TRACE("decoding item %d\n", i);
309 else
310 TRACE("sizing item %d\n", i);
311 ret = items[i].decodeFunc(dwCertEncodingType,
312 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
313 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
314 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
315 : NULL, &items[i].size);
316 if (ret)
318 /* Account for alignment padding */
319 if (items[i].size % sizeof(DWORD))
320 items[i].size += sizeof(DWORD) -
321 items[i].size % sizeof(DWORD);
322 TRACE("item %d size: %d\n", i, items[i].size);
323 if (nextData && items[i].hasPointer &&
324 items[i].size > items[i].minSize)
325 nextData += items[i].size - items[i].minSize;
326 ptr += 1 + nextItemLenBytes + nextItemLen;
327 decoded += 1 + nextItemLenBytes + nextItemLen;
328 TRACE("item %d: decoded %d bytes\n", i,
329 1 + nextItemLenBytes + nextItemLen);
331 else if (items[i].optional &&
332 GetLastError() == CRYPT_E_ASN1_BADTAG)
334 TRACE("skipping optional item %d\n", i);
335 items[i].size = items[i].minSize;
336 SetLastError(NOERROR);
337 ret = TRUE;
339 else
340 TRACE("item %d failed: %08x\n", i,
341 GetLastError());
343 else
345 TRACE("item %d: decoded %d bytes\n", i,
346 1 + nextItemLenBytes + nextItemLen);
347 ptr += 1 + nextItemLenBytes + nextItemLen;
348 decoded += 1 + nextItemLenBytes + nextItemLen;
349 items[i].size = items[i].minSize;
352 else if (items[i].optional)
354 TRACE("skipping optional item %d\n", i);
355 items[i].size = items[i].minSize;
357 else
359 TRACE("item %d: tag %02x doesn't match expected %02x\n",
360 i, ptr[0], items[i].tag);
361 SetLastError(CRYPT_E_ASN1_BADTAG);
362 ret = FALSE;
366 else if (items[i].optional)
368 TRACE("missing optional item %d, skipping\n", i);
369 items[i].size = items[i].minSize;
371 else
373 TRACE("not enough bytes for item %d, failing\n", i);
374 SetLastError(CRYPT_E_ASN1_CORRUPT);
375 ret = FALSE;
378 if (ret)
379 *cbDecoded = decoded;
380 TRACE("returning %d\n", ret);
381 return ret;
384 /* This decodes an arbitrary sequence into a contiguous block of memory
385 * (basically, a struct.) Each element being decoded is described by a struct
386 * AsnDecodeSequenceItem, see above.
387 * startingPointer is an optional pointer to the first place where dynamic
388 * data will be stored. If you know the starting offset, you may pass it
389 * here. Otherwise, pass NULL, and one will be inferred from the items.
390 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
392 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
393 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
394 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
395 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
397 BOOL ret;
399 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
400 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
401 startingPointer);
403 if (pbEncoded[0] == ASN_SEQUENCE)
405 DWORD dataLen;
407 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
409 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
410 const BYTE *ptr = pbEncoded + 1 + lenBytes;
412 cbEncoded -= 1 + lenBytes;
413 if (cbEncoded < dataLen)
415 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
416 cbEncoded);
417 SetLastError(CRYPT_E_ASN1_CORRUPT);
418 ret = FALSE;
420 else
421 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
422 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
423 if (ret && cbDecoded != dataLen)
425 TRACE("expected %d decoded, got %d, failing\n", dataLen,
426 cbDecoded);
427 SetLastError(CRYPT_E_ASN1_CORRUPT);
428 ret = FALSE;
430 if (ret)
432 DWORD i, bytesNeeded = 0, structSize = 0;
434 for (i = 0; i < cItem; i++)
436 bytesNeeded += items[i].size;
437 structSize += items[i].minSize;
439 if (!pvStructInfo)
440 *pcbStructInfo = bytesNeeded;
441 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
442 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
444 BYTE *nextData;
446 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
447 pvStructInfo = *(BYTE **)pvStructInfo;
448 if (startingPointer)
449 nextData = (BYTE *)startingPointer;
450 else
451 nextData = (BYTE *)pvStructInfo + structSize;
452 memset(pvStructInfo, 0, structSize);
453 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
454 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
455 &cbDecoded);
460 else
462 SetLastError(CRYPT_E_ASN1_BADTAG);
463 ret = FALSE;
465 TRACE("returning %d (%08x)\n", ret, GetLastError());
466 return ret;
469 /* tag:
470 * The expected tag of the entire encoded array (usually a variant
471 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
472 * regardless of the tag seen.
473 * decodeFunc:
474 * used to decode each item in the array
475 * itemSize:
476 * is the minimum size of each decoded item
477 * hasPointer:
478 * indicates whether each item has a dynamic pointer
479 * pointerOffset:
480 * indicates the offset within itemSize at which the pointer exists
482 struct AsnArrayDescriptor
484 BYTE tag;
485 CryptDecodeObjectExFunc decodeFunc;
486 DWORD itemSize;
487 BOOL hasPointer;
488 DWORD pointerOffset;
491 struct AsnArrayItemSize
493 DWORD encodedLen;
494 DWORD size;
497 /* Decodes an array of like types into a struct GenericArray.
498 * The layout and decoding of the array are described by a struct
499 * AsnArrayDescriptor.
501 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
502 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
503 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
504 void *startingPointer)
506 BOOL ret = TRUE;
508 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
509 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
510 startingPointer);
512 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
514 DWORD dataLen;
516 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
518 DWORD bytesNeeded, cItems = 0;
519 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
520 /* There can be arbitrarily many items, but there is often only one.
522 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
524 bytesNeeded = sizeof(struct GenericArray);
525 if (dataLen)
527 const BYTE *ptr;
529 for (ptr = pbEncoded + 1 + lenBytes; ret &&
530 ptr - pbEncoded - 1 - lenBytes < dataLen; )
532 DWORD itemLenBytes, itemDataLen, size = 0;
534 itemLenBytes = GET_LEN_BYTES(ptr[1]);
535 /* Each item decoded may not tolerate extraneous bytes, so
536 * get the length of the next element and pass it directly.
538 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
539 &itemDataLen);
540 if (ret)
541 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
542 1 + itemLenBytes + itemDataLen,
543 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
544 &size);
545 if (ret)
547 DWORD nextLen;
549 cItems++;
550 if (itemSizes != &itemSize)
551 itemSizes = CryptMemRealloc(itemSizes,
552 cItems * sizeof(struct AsnArrayItemSize));
553 else
555 itemSizes =
556 CryptMemAlloc(
557 cItems * sizeof(struct AsnArrayItemSize));
558 if (itemSizes)
559 memcpy(itemSizes, &itemSize, sizeof(itemSize));
561 if (itemSizes)
563 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
564 + itemDataLen;
565 itemSizes[cItems - 1].size = size;
566 bytesNeeded += size;
567 ret = CRYPT_GetLen(ptr,
568 cbEncoded - (ptr - pbEncoded), &nextLen);
569 if (ret)
570 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
572 else
573 ret = FALSE;
577 if (ret)
579 if (!pvStructInfo)
580 *pcbStructInfo = bytesNeeded;
581 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
582 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
584 DWORD i;
585 BYTE *nextData;
586 const BYTE *ptr;
587 struct GenericArray *array;
589 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
590 pvStructInfo = *(BYTE **)pvStructInfo;
591 array = (struct GenericArray *)pvStructInfo;
592 array->cItems = cItems;
593 if (startingPointer)
594 array->rgItems = startingPointer;
595 else
596 array->rgItems = (BYTE *)array +
597 sizeof(struct GenericArray);
598 nextData = (BYTE *)array->rgItems +
599 array->cItems * arrayDesc->itemSize;
600 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
601 i < cItems && ptr - pbEncoded - 1 - lenBytes <
602 dataLen; i++)
604 if (arrayDesc->hasPointer)
605 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
606 + arrayDesc->pointerOffset) = nextData;
607 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
608 itemSizes[i].encodedLen,
609 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
610 array->rgItems + i * arrayDesc->itemSize,
611 &itemSizes[i].size);
612 if (ret)
614 DWORD nextLen;
616 nextData += itemSizes[i].size - arrayDesc->itemSize;
617 ret = CRYPT_GetLen(ptr,
618 cbEncoded - (ptr - pbEncoded), &nextLen);
619 if (ret)
620 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
625 if (itemSizes != &itemSize)
626 CryptMemFree(itemSizes);
629 else
631 SetLastError(CRYPT_E_ASN1_BADTAG);
632 ret = FALSE;
634 return ret;
637 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
638 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
639 * to CRYPT_E_ASN1_CORRUPT.
640 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
641 * set!
643 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
644 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
645 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
647 BOOL ret;
648 DWORD dataLen;
650 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
652 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
653 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
655 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
656 bytesNeeded += 1 + lenBytes + dataLen;
658 if (!pvStructInfo)
659 *pcbStructInfo = bytesNeeded;
660 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
661 pvStructInfo, pcbStructInfo, bytesNeeded)))
663 CRYPT_DER_BLOB *blob;
665 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
666 pvStructInfo = *(BYTE **)pvStructInfo;
667 blob = (CRYPT_DER_BLOB *)pvStructInfo;
668 blob->cbData = 1 + lenBytes + dataLen;
669 if (blob->cbData)
671 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
672 blob->pbData = (BYTE *)pbEncoded;
673 else
675 assert(blob->pbData);
676 memcpy(blob->pbData, pbEncoded, blob->cbData);
679 else
681 SetLastError(CRYPT_E_ASN1_CORRUPT);
682 ret = FALSE;
686 return ret;
689 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
690 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
691 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
692 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
694 BOOL ret;
696 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
697 pDecodePara, pvStructInfo, *pcbStructInfo);
699 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
700 * place.
702 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
703 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
704 pvStructInfo, pcbStructInfo);
705 if (ret && pvStructInfo)
707 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
709 if (blob->cbData)
711 DWORD i;
712 BYTE temp;
714 for (i = 0; i < blob->cbData / 2; i++)
716 temp = blob->pbData[i];
717 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
718 blob->pbData[blob->cbData - i - 1] = temp;
722 TRACE("returning %d (%08x)\n", ret, GetLastError());
723 return ret;
726 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
727 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
728 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
730 BOOL ret = TRUE;
732 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
733 pDecodePara, pvStructInfo, *pcbStructInfo);
735 __TRY
737 struct AsnDecodeSequenceItem items[] = {
738 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
739 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
740 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
741 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
742 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
743 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
744 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
745 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
746 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
747 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
750 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
751 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
752 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
753 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
754 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
756 __EXCEPT_PAGE_FAULT
758 SetLastError(STATUS_ACCESS_VIOLATION);
759 ret = FALSE;
761 __ENDTRY
763 TRACE("Returning %d (%08x)\n", ret, GetLastError());
764 return ret;
767 /* Internal function */
768 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
769 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
770 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
772 BOOL ret;
773 DWORD dataLen;
775 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
777 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
779 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
780 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
781 pvStructInfo, pcbStructInfo);
783 return ret;
786 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
787 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
788 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
790 BOOL ret;
792 struct AsnDecodeSequenceItem items[] = {
793 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
794 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
795 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
796 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
799 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
800 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
801 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
802 return ret;
805 /* Internal function */
806 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
807 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
808 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
810 BOOL ret;
811 DWORD dataLen;
813 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
815 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
817 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
818 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
819 pDecodePara, pvStructInfo, pcbStructInfo);
821 return ret;
824 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
825 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
826 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
828 BOOL ret = TRUE;
829 struct AsnDecodeSequenceItem items[] = {
830 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
831 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
832 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
833 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
834 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
835 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
836 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
837 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
838 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
839 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
840 Issuer.pbData) },
841 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
842 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
843 FALSE, 0 },
844 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
845 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
846 Subject.pbData) },
847 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
848 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
849 FALSE, TRUE, offsetof(CERT_INFO,
850 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
851 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
852 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
853 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
854 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
855 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
856 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
857 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
858 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
859 offsetof(CERT_INFO, rgExtension), 0 },
862 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
863 pDecodePara, pvStructInfo, *pcbStructInfo);
865 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
866 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
867 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
868 if (ret && pvStructInfo)
870 CERT_INFO *info;
872 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
873 info = *(CERT_INFO **)pvStructInfo;
874 else
875 info = (CERT_INFO *)pvStructInfo;
876 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
877 !info->Subject.cbData)
879 SetLastError(CRYPT_E_ASN1_CORRUPT);
880 /* Don't need to deallocate, because it should have failed on the
881 * first pass (and no memory was allocated.)
883 ret = FALSE;
887 TRACE("Returning %d (%08x)\n", ret, GetLastError());
888 return ret;
891 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
892 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
893 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
895 BOOL ret = FALSE;
897 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
898 pDecodePara, pvStructInfo, *pcbStructInfo);
900 __TRY
902 DWORD size = 0;
904 /* Unless told not to, first try to decode it as a signed cert. */
905 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
907 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
909 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
910 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
911 (BYTE *)&signedCert, &size);
912 if (ret)
914 size = 0;
915 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
916 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
917 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
918 pvStructInfo, pcbStructInfo);
919 LocalFree(signedCert);
922 /* Failing that, try it as an unsigned cert */
923 if (!ret)
925 size = 0;
926 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
927 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
928 pDecodePara, pvStructInfo, pcbStructInfo);
931 __EXCEPT_PAGE_FAULT
933 SetLastError(STATUS_ACCESS_VIOLATION);
935 __ENDTRY
937 TRACE("Returning %d (%08x)\n", ret, GetLastError());
938 return ret;
941 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
942 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
943 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
945 BOOL ret;
946 struct AsnDecodeSequenceItem items[] = {
947 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
948 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
949 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
950 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
951 sizeof(FILETIME), FALSE, FALSE, 0 },
952 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
953 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
954 offsetof(CRL_ENTRY, rgExtension), 0 },
956 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
958 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
959 *pcbStructInfo);
961 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
962 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
963 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
964 return ret;
967 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
968 * been set prior to calling.
970 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
971 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
972 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
974 BOOL ret;
975 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
976 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
977 offsetof(CRL_ENTRY, SerialNumber.pbData) };
978 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
980 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
981 pDecodePara, pvStructInfo, *pcbStructInfo);
983 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
984 pDecodePara, pvStructInfo, pcbStructInfo,
985 entries ? entries->rgItems : NULL);
986 TRACE("Returning %d (%08x)\n", ret, GetLastError());
987 return ret;
990 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
991 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
992 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
994 struct AsnDecodeSequenceItem items[] = {
995 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
996 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
997 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
998 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
999 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1000 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1001 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1002 Issuer.pbData) },
1003 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
1004 sizeof(FILETIME), FALSE, FALSE, 0 },
1005 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
1006 sizeof(FILETIME), TRUE, FALSE, 0 },
1007 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1008 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1009 offsetof(CRL_INFO, rgCRLEntry), 0 },
1010 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1011 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1012 offsetof(CRL_INFO, rgExtension), 0 },
1014 BOOL ret = TRUE;
1016 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1017 pDecodePara, pvStructInfo, *pcbStructInfo);
1019 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1020 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1021 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1023 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1024 return ret;
1027 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1028 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1029 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1031 BOOL ret = FALSE;
1033 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1034 pDecodePara, pvStructInfo, *pcbStructInfo);
1036 __TRY
1038 DWORD size = 0;
1040 /* Unless told not to, first try to decode it as a signed crl. */
1041 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1043 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1045 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1046 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1047 (BYTE *)&signedCrl, &size);
1048 if (ret)
1050 size = 0;
1051 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1052 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1053 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1054 pvStructInfo, pcbStructInfo);
1055 LocalFree(signedCrl);
1058 /* Failing that, try it as an unsigned crl */
1059 if (!ret)
1061 size = 0;
1062 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1063 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1064 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1067 __EXCEPT_PAGE_FAULT
1069 SetLastError(STATUS_ACCESS_VIOLATION);
1071 __ENDTRY
1073 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1074 return ret;
1077 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType,
1078 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1079 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1081 BOOL ret = TRUE;
1082 DWORD dataLen;
1084 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1085 pDecodePara, pvStructInfo, *pcbStructInfo);
1087 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1089 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1090 DWORD bytesNeeded = sizeof(LPSTR);
1092 if (dataLen)
1094 /* The largest possible string for the first two components
1095 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1097 char firstTwo[6];
1098 const BYTE *ptr;
1100 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1101 pbEncoded[1 + lenBytes] / 40,
1102 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1103 * 40);
1104 bytesNeeded += strlen(firstTwo) + 1;
1105 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1106 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1108 /* large enough for ".4000000" */
1109 char str[9];
1110 int val = 0;
1112 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1113 (*ptr & 0x80))
1115 val <<= 7;
1116 val |= *ptr & 0x7f;
1117 ptr++;
1119 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1120 (*ptr & 0x80))
1122 SetLastError(CRYPT_E_ASN1_CORRUPT);
1123 ret = FALSE;
1125 else
1127 val <<= 7;
1128 val |= *ptr++;
1129 snprintf(str, sizeof(str), ".%d", val);
1130 bytesNeeded += strlen(str);
1134 if (!pvStructInfo)
1135 *pcbStructInfo = bytesNeeded;
1136 else if (*pcbStructInfo < bytesNeeded)
1138 *pcbStructInfo = bytesNeeded;
1139 SetLastError(ERROR_MORE_DATA);
1140 ret = FALSE;
1142 else
1144 if (dataLen)
1146 const BYTE *ptr;
1147 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1149 *pszObjId = 0;
1150 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1151 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1152 40) * 40);
1153 pszObjId += strlen(pszObjId);
1154 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1155 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1157 int val = 0;
1159 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1160 (*ptr & 0x80))
1162 val <<= 7;
1163 val |= *ptr & 0x7f;
1164 ptr++;
1166 val <<= 7;
1167 val |= *ptr++;
1168 sprintf(pszObjId, ".%d", val);
1169 pszObjId += strlen(pszObjId);
1172 else
1173 *(LPSTR *)pvStructInfo = NULL;
1174 *pcbStructInfo = bytesNeeded;
1177 return ret;
1180 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1181 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1182 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1184 BOOL ret;
1186 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1187 pDecodePara, pvStructInfo, *pcbStructInfo);
1189 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1190 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, lpszStructType,
1191 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
1192 pcbStructInfo);
1193 else
1195 SetLastError(CRYPT_E_ASN1_BADTAG);
1196 ret = FALSE;
1198 return ret;
1201 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1202 * ahead of time!
1204 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1205 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1206 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1208 struct AsnDecodeSequenceItem items[] = {
1209 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1210 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1211 offsetof(CERT_EXTENSION, pszObjId), 0 },
1212 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1213 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1214 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1215 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1216 offsetof(CERT_EXTENSION, Value.pbData) },
1218 BOOL ret = TRUE;
1219 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1221 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1222 *pcbStructInfo);
1224 if (ext)
1225 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1226 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1227 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1228 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1229 if (ext)
1230 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1231 debugstr_a(ext->pszObjId));
1232 TRACE("returning %d (%08x)\n", ret, GetLastError());
1233 return ret;
1236 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1237 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1238 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1240 BOOL ret = TRUE;
1241 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1242 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1243 offsetof(CERT_EXTENSION, pszObjId) };
1244 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1246 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1247 pDecodePara, pvStructInfo, *pcbStructInfo);
1249 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1250 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1251 return ret;
1254 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1255 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1256 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1258 BOOL ret = TRUE;
1260 __TRY
1262 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1263 lpszStructType, pbEncoded, cbEncoded,
1264 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1265 if (ret && pvStructInfo)
1267 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1268 pcbStructInfo, *pcbStructInfo);
1269 if (ret)
1271 CERT_EXTENSIONS *exts;
1273 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1274 pvStructInfo = *(BYTE **)pvStructInfo;
1275 exts = (CERT_EXTENSIONS *)pvStructInfo;
1276 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1277 sizeof(CERT_EXTENSIONS));
1278 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1279 lpszStructType, pbEncoded, cbEncoded,
1280 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1281 pcbStructInfo);
1285 __EXCEPT_PAGE_FAULT
1287 SetLastError(STATUS_ACCESS_VIOLATION);
1288 ret = FALSE;
1290 __ENDTRY
1291 return ret;
1294 /* Warning: this assumes the address of value->Value.pbData is already set, in
1295 * order to avoid overwriting memory. (In some cases, it may change it, if it
1296 * doesn't copy anything to memory.) Be sure to set it correctly!
1298 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1299 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1300 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1302 BOOL ret = TRUE;
1303 DWORD dataLen;
1304 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1306 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1308 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1309 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1311 switch (pbEncoded[0])
1313 case ASN_OCTETSTRING:
1314 valueType = CERT_RDN_OCTET_STRING;
1315 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1316 bytesNeeded += dataLen;
1317 break;
1318 case ASN_NUMERICSTRING:
1319 valueType = CERT_RDN_NUMERIC_STRING;
1320 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1321 bytesNeeded += dataLen;
1322 break;
1323 case ASN_PRINTABLESTRING:
1324 valueType = CERT_RDN_PRINTABLE_STRING;
1325 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1326 bytesNeeded += dataLen;
1327 break;
1328 case ASN_IA5STRING:
1329 valueType = CERT_RDN_IA5_STRING;
1330 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1331 bytesNeeded += dataLen;
1332 break;
1333 case ASN_T61STRING:
1334 valueType = CERT_RDN_T61_STRING;
1335 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1336 bytesNeeded += dataLen;
1337 break;
1338 case ASN_VIDEOTEXSTRING:
1339 valueType = CERT_RDN_VIDEOTEX_STRING;
1340 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1341 bytesNeeded += dataLen;
1342 break;
1343 case ASN_GRAPHICSTRING:
1344 valueType = CERT_RDN_GRAPHIC_STRING;
1345 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1346 bytesNeeded += dataLen;
1347 break;
1348 case ASN_VISIBLESTRING:
1349 valueType = CERT_RDN_VISIBLE_STRING;
1350 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1351 bytesNeeded += dataLen;
1352 break;
1353 case ASN_GENERALSTRING:
1354 valueType = CERT_RDN_GENERAL_STRING;
1355 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1356 bytesNeeded += dataLen;
1357 break;
1358 case ASN_UNIVERSALSTRING:
1359 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1360 SetLastError(CRYPT_E_ASN1_BADTAG);
1361 return FALSE;
1362 case ASN_BMPSTRING:
1363 valueType = CERT_RDN_BMP_STRING;
1364 bytesNeeded += dataLen;
1365 break;
1366 case ASN_UTF8STRING:
1367 valueType = CERT_RDN_UTF8_STRING;
1368 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1369 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1370 break;
1371 default:
1372 SetLastError(CRYPT_E_ASN1_BADTAG);
1373 return FALSE;
1376 if (!value)
1377 *pcbStructInfo = bytesNeeded;
1378 else if (*pcbStructInfo < bytesNeeded)
1380 *pcbStructInfo = bytesNeeded;
1381 SetLastError(ERROR_MORE_DATA);
1382 ret = FALSE;
1384 else
1386 *pcbStructInfo = bytesNeeded;
1387 value->dwValueType = valueType;
1388 if (dataLen)
1390 DWORD i;
1392 assert(value->Value.pbData);
1393 switch (pbEncoded[0])
1395 case ASN_OCTETSTRING:
1396 case ASN_NUMERICSTRING:
1397 case ASN_PRINTABLESTRING:
1398 case ASN_IA5STRING:
1399 case ASN_T61STRING:
1400 case ASN_VIDEOTEXSTRING:
1401 case ASN_GRAPHICSTRING:
1402 case ASN_VISIBLESTRING:
1403 case ASN_GENERALSTRING:
1404 value->Value.cbData = dataLen;
1405 if (dataLen)
1407 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1408 memcpy(value->Value.pbData,
1409 pbEncoded + 1 + lenBytes, dataLen);
1410 else
1411 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1412 lenBytes;
1414 break;
1415 case ASN_BMPSTRING:
1417 LPWSTR str = (LPWSTR)value->Value.pbData;
1419 value->Value.cbData = dataLen;
1420 for (i = 0; i < dataLen / 2; i++)
1421 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1422 pbEncoded[1 + lenBytes + 2 * i + 1];
1423 break;
1425 case ASN_UTF8STRING:
1427 LPWSTR str = (LPWSTR)value->Value.pbData;
1429 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1430 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1431 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1432 break;
1436 else
1438 value->Value.cbData = 0;
1439 value->Value.pbData = NULL;
1443 return ret;
1446 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1447 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1448 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1450 BOOL ret = TRUE;
1452 __TRY
1454 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1455 lpszStructType, pbEncoded, cbEncoded,
1456 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1457 if (ret && pvStructInfo)
1459 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1460 pcbStructInfo, *pcbStructInfo);
1461 if (ret)
1463 CERT_NAME_VALUE *value;
1465 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1466 pvStructInfo = *(BYTE **)pvStructInfo;
1467 value = (CERT_NAME_VALUE *)pvStructInfo;
1468 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1469 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1470 lpszStructType, pbEncoded, cbEncoded,
1471 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1472 pcbStructInfo);
1476 __EXCEPT_PAGE_FAULT
1478 SetLastError(STATUS_ACCESS_VIOLATION);
1479 ret = FALSE;
1481 __ENDTRY
1482 return ret;
1485 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1486 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1487 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1488 void *pvStructInfo, DWORD *pcbStructInfo)
1490 BOOL ret = TRUE;
1491 DWORD dataLen;
1492 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1494 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1496 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1497 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1499 switch (pbEncoded[0])
1501 case ASN_NUMERICSTRING:
1502 valueType = CERT_RDN_NUMERIC_STRING;
1503 bytesNeeded += dataLen * 2;
1504 break;
1505 case ASN_PRINTABLESTRING:
1506 valueType = CERT_RDN_PRINTABLE_STRING;
1507 bytesNeeded += dataLen * 2;
1508 break;
1509 case ASN_IA5STRING:
1510 valueType = CERT_RDN_IA5_STRING;
1511 bytesNeeded += dataLen * 2;
1512 break;
1513 case ASN_T61STRING:
1514 valueType = CERT_RDN_T61_STRING;
1515 bytesNeeded += dataLen * 2;
1516 break;
1517 case ASN_VIDEOTEXSTRING:
1518 valueType = CERT_RDN_VIDEOTEX_STRING;
1519 bytesNeeded += dataLen * 2;
1520 break;
1521 case ASN_GRAPHICSTRING:
1522 valueType = CERT_RDN_GRAPHIC_STRING;
1523 bytesNeeded += dataLen * 2;
1524 break;
1525 case ASN_VISIBLESTRING:
1526 valueType = CERT_RDN_VISIBLE_STRING;
1527 bytesNeeded += dataLen * 2;
1528 break;
1529 case ASN_GENERALSTRING:
1530 valueType = CERT_RDN_GENERAL_STRING;
1531 bytesNeeded += dataLen * 2;
1532 break;
1533 case ASN_UNIVERSALSTRING:
1534 valueType = CERT_RDN_UNIVERSAL_STRING;
1535 bytesNeeded += dataLen / 2;
1536 break;
1537 case ASN_BMPSTRING:
1538 valueType = CERT_RDN_BMP_STRING;
1539 bytesNeeded += dataLen;
1540 break;
1541 case ASN_UTF8STRING:
1542 valueType = CERT_RDN_UTF8_STRING;
1543 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1544 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1545 break;
1546 default:
1547 SetLastError(CRYPT_E_ASN1_BADTAG);
1548 return FALSE;
1551 if (!value)
1552 *pcbStructInfo = bytesNeeded;
1553 else if (*pcbStructInfo < bytesNeeded)
1555 *pcbStructInfo = bytesNeeded;
1556 SetLastError(ERROR_MORE_DATA);
1557 ret = FALSE;
1559 else
1561 *pcbStructInfo = bytesNeeded;
1562 value->dwValueType = valueType;
1563 if (dataLen)
1565 DWORD i;
1566 LPWSTR str = (LPWSTR)value->Value.pbData;
1568 assert(value->Value.pbData);
1569 switch (pbEncoded[0])
1571 case ASN_NUMERICSTRING:
1572 case ASN_PRINTABLESTRING:
1573 case ASN_IA5STRING:
1574 case ASN_T61STRING:
1575 case ASN_VIDEOTEXSTRING:
1576 case ASN_GRAPHICSTRING:
1577 case ASN_VISIBLESTRING:
1578 case ASN_GENERALSTRING:
1579 value->Value.cbData = dataLen * 2;
1580 for (i = 0; i < dataLen; i++)
1581 str[i] = pbEncoded[1 + lenBytes + i];
1582 break;
1583 case ASN_UNIVERSALSTRING:
1584 value->Value.cbData = dataLen / 2;
1585 for (i = 0; i < dataLen / 4; i++)
1586 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1587 | pbEncoded[1 + lenBytes + 2 * i + 3];
1588 break;
1589 case ASN_BMPSTRING:
1590 value->Value.cbData = dataLen;
1591 for (i = 0; i < dataLen / 2; i++)
1592 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1593 pbEncoded[1 + lenBytes + 2 * i + 1];
1594 break;
1595 case ASN_UTF8STRING:
1596 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1597 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1598 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1599 break;
1602 else
1604 value->Value.cbData = 0;
1605 value->Value.pbData = NULL;
1609 return ret;
1612 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1613 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1614 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1616 BOOL ret = TRUE;
1618 __TRY
1620 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1621 lpszStructType, pbEncoded, cbEncoded,
1622 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1623 if (ret && pvStructInfo)
1625 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1626 pcbStructInfo, *pcbStructInfo);
1627 if (ret)
1629 CERT_NAME_VALUE *value;
1631 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1632 pvStructInfo = *(BYTE **)pvStructInfo;
1633 value = (CERT_NAME_VALUE *)pvStructInfo;
1634 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1635 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1636 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1637 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1638 pcbStructInfo);
1642 __EXCEPT_PAGE_FAULT
1644 SetLastError(STATUS_ACCESS_VIOLATION);
1645 ret = FALSE;
1647 __ENDTRY
1648 return ret;
1651 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1652 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1653 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1655 BOOL ret;
1656 struct AsnDecodeSequenceItem items[] = {
1657 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1658 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1659 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1660 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1661 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1662 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1664 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1666 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1667 pvStructInfo, *pcbStructInfo);
1669 if (attr)
1670 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1671 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1672 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1673 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1674 if (attr)
1676 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1677 debugstr_a(attr->pszObjId));
1678 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1680 TRACE("returning %d (%08x)\n", ret, GetLastError());
1681 return ret;
1684 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1685 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1686 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1688 BOOL ret = TRUE;
1689 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1690 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1691 offsetof(CERT_RDN_ATTR, pszObjId) };
1692 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1694 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1695 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1696 return ret;
1699 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1700 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1701 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1703 BOOL ret = TRUE;
1705 __TRY
1707 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1708 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1709 offsetof(CERT_RDN, rgRDNAttr) };
1711 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1712 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1714 __EXCEPT_PAGE_FAULT
1716 SetLastError(STATUS_ACCESS_VIOLATION);
1717 ret = FALSE;
1719 __ENDTRY
1720 return ret;
1723 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
1724 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1725 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1727 BOOL ret;
1728 struct AsnDecodeSequenceItem items[] = {
1729 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1730 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1731 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1732 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1733 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1734 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1736 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1738 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1739 pvStructInfo, *pcbStructInfo);
1741 if (attr)
1742 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1743 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1744 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1745 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1746 if (attr)
1748 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1749 debugstr_a(attr->pszObjId));
1750 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1752 TRACE("returning %d (%08x)\n", ret, GetLastError());
1753 return ret;
1756 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
1757 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1758 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1760 BOOL ret = TRUE;
1761 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1762 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1763 offsetof(CERT_RDN_ATTR, pszObjId) };
1764 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1766 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1767 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1768 return ret;
1771 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1772 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1773 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1775 BOOL ret = TRUE;
1777 __TRY
1779 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1780 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1781 offsetof(CERT_RDN, rgRDNAttr) };
1783 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1784 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1786 __EXCEPT_PAGE_FAULT
1788 SetLastError(STATUS_ACCESS_VIOLATION);
1789 ret = FALSE;
1791 __ENDTRY
1792 return ret;
1795 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1796 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1797 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1799 BOOL ret = TRUE;
1800 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1802 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1803 pDecodePara, pvStructInfo, *pcbStructInfo);
1805 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1806 bytesNeeded += cbEncoded;
1807 if (!pvStructInfo)
1808 *pcbStructInfo = bytesNeeded;
1809 else if (*pcbStructInfo < bytesNeeded)
1811 SetLastError(ERROR_MORE_DATA);
1812 *pcbStructInfo = bytesNeeded;
1813 ret = FALSE;
1815 else
1817 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1819 *pcbStructInfo = bytesNeeded;
1820 blob->cbData = cbEncoded;
1821 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1822 blob->pbData = (LPBYTE)pbEncoded;
1823 else
1825 assert(blob->pbData);
1826 memcpy(blob->pbData, pbEncoded, blob->cbData);
1829 return ret;
1832 static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType,
1833 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1834 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1836 BOOL ret;
1837 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
1838 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1839 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1841 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1842 pDecodePara, pvStructInfo, *pcbStructInfo);
1844 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1845 pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
1846 return ret;
1849 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1850 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1851 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1853 BOOL ret = FALSE;
1855 __TRY
1857 struct AsnDecodeSequenceItem items[] = {
1858 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1859 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1860 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1861 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1862 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1863 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1865 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1867 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1868 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1869 pDecodePara, pvStructInfo, pcbStructInfo, attr ? attr->pszObjId :
1870 NULL);
1872 __EXCEPT_PAGE_FAULT
1874 SetLastError(STATUS_ACCESS_VIOLATION);
1876 __ENDTRY
1877 TRACE("returning %d\n", ret);
1878 return ret;
1881 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal(
1882 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1883 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1884 void *pvStructInfo, DWORD *pcbStructInfo)
1886 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodePKCSAttribute,
1887 sizeof(CRYPT_ATTRIBUTE), TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
1888 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1889 BOOL ret;
1891 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1892 pDecodePara, pvStructInfo, pcbStructInfo, attrs ? attrs->rgAttr :
1893 NULL);
1894 return ret;
1897 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
1898 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1899 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1901 BOOL ret = FALSE;
1903 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1904 pDecodePara, pvStructInfo, *pcbStructInfo);
1906 __TRY
1908 DWORD bytesNeeded;
1910 if (!cbEncoded)
1911 SetLastError(CRYPT_E_ASN1_EOD);
1912 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
1913 SetLastError(CRYPT_E_ASN1_CORRUPT);
1914 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(
1915 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1916 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1918 if (!pvStructInfo)
1919 *pcbStructInfo = bytesNeeded;
1920 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1921 pvStructInfo, pcbStructInfo, bytesNeeded)))
1923 PCRYPT_ATTRIBUTES attrs;
1925 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1926 pvStructInfo = *(BYTE **)pvStructInfo;
1927 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1928 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
1929 sizeof(CRYPT_ATTRIBUTES));
1930 ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1931 lpszStructType, pbEncoded, cbEncoded,
1932 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1933 &bytesNeeded);
1937 __EXCEPT_PAGE_FAULT
1939 SetLastError(STATUS_ACCESS_VIOLATION);
1941 __ENDTRY
1942 TRACE("returning %d\n", ret);
1943 return ret;
1946 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1947 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1948 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1950 CRYPT_ALGORITHM_IDENTIFIER *algo =
1951 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1952 BOOL ret = TRUE;
1953 struct AsnDecodeSequenceItem items[] = {
1954 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1955 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1956 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1957 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1958 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1959 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1962 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1963 pDecodePara, pvStructInfo, *pcbStructInfo);
1965 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1966 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1967 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1968 if (ret && pvStructInfo)
1970 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1971 debugstr_a(algo->pszObjId));
1973 return ret;
1976 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1977 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1978 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1980 BOOL ret = TRUE;
1981 struct AsnDecodeSequenceItem items[] = {
1982 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1983 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1984 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1985 Algorithm.pszObjId) },
1986 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1987 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1988 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1990 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1992 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1993 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1994 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1995 info->Algorithm.Parameters.pbData : NULL);
1996 return ret;
1999 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2000 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2001 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2003 BOOL ret = TRUE;
2005 __TRY
2007 DWORD bytesNeeded;
2009 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2010 lpszStructType, pbEncoded, cbEncoded,
2011 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2013 if (!pvStructInfo)
2014 *pcbStructInfo = bytesNeeded;
2015 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2016 pvStructInfo, pcbStructInfo, bytesNeeded)))
2018 PCERT_PUBLIC_KEY_INFO info;
2020 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2021 pvStructInfo = *(BYTE **)pvStructInfo;
2022 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2023 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2024 sizeof(CERT_PUBLIC_KEY_INFO);
2025 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2026 lpszStructType, pbEncoded, cbEncoded,
2027 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2028 &bytesNeeded);
2032 __EXCEPT_PAGE_FAULT
2034 SetLastError(STATUS_ACCESS_VIOLATION);
2035 ret = FALSE;
2037 __ENDTRY
2038 return ret;
2041 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2042 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2043 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2045 BOOL ret;
2047 if (cbEncoded < 3)
2049 SetLastError(CRYPT_E_ASN1_CORRUPT);
2050 return FALSE;
2052 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2054 SetLastError(CRYPT_E_ASN1_CORRUPT);
2055 return FALSE;
2057 if (pbEncoded[1] > 1)
2059 SetLastError(CRYPT_E_ASN1_CORRUPT);
2060 return FALSE;
2062 if (!pvStructInfo)
2064 *pcbStructInfo = sizeof(BOOL);
2065 ret = TRUE;
2067 else if (*pcbStructInfo < sizeof(BOOL))
2069 *pcbStructInfo = sizeof(BOOL);
2070 SetLastError(ERROR_MORE_DATA);
2071 ret = FALSE;
2073 else
2075 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2076 ret = TRUE;
2078 TRACE("returning %d (%08x)\n", ret, GetLastError());
2079 return ret;
2082 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
2083 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2084 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2086 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2087 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2088 BOOL ret;
2090 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2091 pDecodePara, pvStructInfo, *pcbStructInfo);
2093 if (cbEncoded < 2)
2095 SetLastError(CRYPT_E_ASN1_CORRUPT);
2096 return FALSE;
2098 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2099 if (1 + lenBytes > cbEncoded)
2101 SetLastError(CRYPT_E_ASN1_CORRUPT);
2102 return FALSE;
2104 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2106 switch (pbEncoded[0] & ASN_TYPE_MASK)
2108 case 1: /* rfc822Name */
2109 case 2: /* dNSName */
2110 case 6: /* uniformResourceIdentifier */
2111 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2112 break;
2113 case 4: /* directoryName */
2114 case 7: /* iPAddress */
2115 bytesNeeded += dataLen;
2116 break;
2117 case 8: /* registeredID */
2118 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, NULL,
2119 pbEncoded, cbEncoded, 0, NULL, NULL, &dataLen);
2120 if (ret)
2122 /* FIXME: ugly, shouldn't need to know internals of OID decode
2123 * function to use it.
2125 bytesNeeded += dataLen - sizeof(LPSTR);
2127 break;
2128 case 0: /* otherName */
2129 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2130 SetLastError(CRYPT_E_ASN1_BADTAG);
2131 ret = FALSE;
2132 break;
2133 case 3: /* x400Address, unimplemented */
2134 case 5: /* ediPartyName, unimplemented */
2135 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2136 SetLastError(CRYPT_E_ASN1_BADTAG);
2137 ret = FALSE;
2138 break;
2139 default:
2140 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2141 SetLastError(CRYPT_E_ASN1_CORRUPT);
2142 ret = FALSE;
2144 if (ret)
2146 if (!entry)
2147 *pcbStructInfo = bytesNeeded;
2148 else if (*pcbStructInfo < bytesNeeded)
2150 *pcbStructInfo = bytesNeeded;
2151 SetLastError(ERROR_MORE_DATA);
2152 ret = FALSE;
2154 else
2156 *pcbStructInfo = bytesNeeded;
2157 /* MS used values one greater than the asn1 ones.. sigh */
2158 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2159 switch (pbEncoded[0] & ASN_TYPE_MASK)
2161 case 1: /* rfc822Name */
2162 case 2: /* dNSName */
2163 case 6: /* uniformResourceIdentifier */
2165 DWORD i;
2167 for (i = 0; i < dataLen; i++)
2168 entry->u.pwszURL[i] =
2169 (WCHAR)pbEncoded[1 + lenBytes + i];
2170 entry->u.pwszURL[i] = 0;
2171 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2172 debugstr_w(entry->u.pwszURL));
2173 break;
2175 case 4: /* directoryName */
2176 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2177 /* The data are memory-equivalent with the IPAddress case,
2178 * fall-through
2180 case 7: /* iPAddress */
2181 /* The next data pointer is in the pwszURL spot, that is,
2182 * the first 4 bytes. Need to move it to the next spot.
2184 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2185 entry->u.IPAddress.cbData = dataLen;
2186 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2187 dataLen);
2188 break;
2189 case 8: /* registeredID */
2190 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, NULL,
2191 pbEncoded, cbEncoded, 0, NULL, &entry->u.pszRegisteredID,
2192 &dataLen);
2193 break;
2198 return ret;
2201 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2202 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2203 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2205 BOOL ret = TRUE;
2206 struct AsnArrayDescriptor arrayDesc = { 0,
2207 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2208 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2209 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2211 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2212 pDecodePara, pvStructInfo, *pcbStructInfo);
2214 if (info)
2215 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2216 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2217 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2218 return ret;
2221 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2222 static BOOL WINAPI CRYPT_AsnDecodeIntegerSwapBytes(DWORD dwCertEncodingType,
2223 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2224 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2226 BOOL ret;
2228 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2229 pDecodePara, pvStructInfo, *pcbStructInfo);
2231 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2232 * place.
2234 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType, lpszStructType,
2235 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
2236 pvStructInfo, pcbStructInfo);
2237 if (ret && pvStructInfo)
2239 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2241 if (blob->cbData)
2243 DWORD i;
2244 BYTE temp;
2246 for (i = 0; i < blob->cbData / 2; i++)
2248 temp = blob->pbData[i];
2249 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2250 blob->pbData[blob->cbData - i - 1] = temp;
2254 TRACE("returning %d (%08x)\n", ret, GetLastError());
2255 return ret;
2258 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2259 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2260 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2262 BOOL ret;
2264 __TRY
2266 struct AsnDecodeSequenceItem items[] = {
2267 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2268 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2269 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2270 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2271 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2272 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2273 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2274 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2275 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2276 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2277 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2280 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2281 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2282 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2284 __EXCEPT_PAGE_FAULT
2286 SetLastError(STATUS_ACCESS_VIOLATION);
2287 ret = FALSE;
2289 __ENDTRY
2290 return ret;
2293 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2294 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2295 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2297 BOOL ret;
2299 __TRY
2301 struct AsnDecodeSequenceItem items[] = {
2302 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2303 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2304 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2305 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2306 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2307 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2308 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2309 AuthorityCertIssuer.rgAltEntry), 0 },
2310 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2311 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2312 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2313 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2314 AuthorityCertSerialNumber.pbData), 0 },
2317 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2318 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2319 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2321 __EXCEPT_PAGE_FAULT
2323 SetLastError(STATUS_ACCESS_VIOLATION);
2324 ret = FALSE;
2326 __ENDTRY
2327 return ret;
2330 static BOOL WINAPI CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType,
2331 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2332 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2334 BOOL ret;
2335 DWORD dataLen;
2337 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2338 pDecodePara, pvStructInfo, *pcbStructInfo);
2340 /* The caller has already checked the tag, no need to check it again.
2341 * Check the outer length is valid by calling CRYPT_GetLen:
2343 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2345 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2346 DWORD innerLen;
2348 pbEncoded += 1 + lenBytes;
2349 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2350 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2352 ret = CRYPT_AsnDecodeCopyBytes(dwCertEncodingType, NULL,
2353 pbEncoded, dataLen, dwFlags, pDecodePara, pvStructInfo,
2354 pcbStructInfo);
2357 return ret;
2360 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfoInternal(
2361 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2362 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2363 void *pvStructInfo, DWORD *pcbStructInfo)
2365 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2366 struct AsnDecodeSequenceItem items[] = {
2367 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2368 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2369 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2370 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2371 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2372 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2373 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2375 BOOL ret;
2377 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2378 pDecodePara, pvStructInfo, *pcbStructInfo);
2380 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2381 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2382 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->pszObjId : NULL);
2383 return ret;
2386 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2387 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2388 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2390 BOOL ret = FALSE;
2392 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2393 pDecodePara, pvStructInfo, *pcbStructInfo);
2395 __TRY
2397 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2398 lpszStructType, pbEncoded, cbEncoded,
2399 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
2400 if (ret && pvStructInfo)
2402 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2403 pcbStructInfo, *pcbStructInfo);
2404 if (ret)
2406 CRYPT_CONTENT_INFO *info;
2408 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2409 pvStructInfo = *(BYTE **)pvStructInfo;
2410 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2411 info->pszObjId = (LPSTR)((BYTE *)info +
2412 sizeof(CRYPT_CONTENT_INFO));
2413 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2414 lpszStructType, pbEncoded, cbEncoded,
2415 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2416 pcbStructInfo);
2420 __EXCEPT_PAGE_FAULT
2422 SetLastError(STATUS_ACCESS_VIOLATION);
2424 __ENDTRY
2425 return ret;
2428 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2429 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2430 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2432 BOOL ret;
2433 struct AsnDecodeSequenceItem items[] = {
2434 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version), CRYPT_AsnDecodeInt,
2435 sizeof(DWORD), FALSE, FALSE, 0, 0 },
2436 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2437 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2438 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2439 0 },
2440 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2441 CRYPT_AsnDecodePKCSContentInfoInternal,
2442 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2443 ContentInfo.pszObjId), 0 },
2444 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2445 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2446 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2449 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
2450 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2451 pDecodePara, digestedData, pcbDigestedData, NULL);
2452 return ret;
2455 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2456 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2457 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2459 BOOL ret = TRUE;
2461 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2462 pDecodePara, pvStructInfo, *pcbStructInfo);
2464 __TRY
2466 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2467 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2468 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2470 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2471 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2473 __EXCEPT_PAGE_FAULT
2475 SetLastError(STATUS_ACCESS_VIOLATION);
2476 ret = FALSE;
2478 __ENDTRY
2479 return ret;
2482 struct PATH_LEN_CONSTRAINT
2484 BOOL fPathLenConstraint;
2485 DWORD dwPathLenConstraint;
2488 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2489 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2490 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2492 BOOL ret = TRUE;
2494 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2495 pvStructInfo, *pcbStructInfo);
2497 if (cbEncoded)
2499 if (pbEncoded[0] == ASN_INTEGER)
2501 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2503 if (!pvStructInfo)
2504 *pcbStructInfo = bytesNeeded;
2505 else if (*pcbStructInfo < bytesNeeded)
2507 SetLastError(ERROR_MORE_DATA);
2508 *pcbStructInfo = bytesNeeded;
2509 ret = FALSE;
2511 else
2513 struct PATH_LEN_CONSTRAINT *constraint =
2514 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2515 DWORD size = sizeof(constraint->dwPathLenConstraint);
2517 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2518 pbEncoded, cbEncoded, 0, NULL,
2519 &constraint->dwPathLenConstraint, &size);
2520 if (ret)
2521 constraint->fPathLenConstraint = TRUE;
2522 TRACE("got an int, dwPathLenConstraint is %d\n",
2523 constraint->dwPathLenConstraint);
2526 else
2528 SetLastError(CRYPT_E_ASN1_CORRUPT);
2529 ret = FALSE;
2532 TRACE("returning %d (%08x)\n", ret, GetLastError());
2533 return ret;
2536 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2537 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2538 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2540 BOOL ret;
2541 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2542 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2543 offsetof(CERT_NAME_BLOB, pbData) };
2544 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2546 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2547 pDecodePara, pvStructInfo, *pcbStructInfo);
2549 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2550 pDecodePara, pvStructInfo, pcbStructInfo,
2551 entries ? entries->rgItems : NULL);
2552 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2553 return ret;
2556 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2557 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2558 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2560 BOOL ret;
2562 __TRY
2564 struct AsnDecodeSequenceItem items[] = {
2565 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2566 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2567 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2568 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2569 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2570 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2571 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2572 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2573 sizeof(struct GenericArray), TRUE, TRUE,
2574 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2577 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2578 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2579 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2581 __EXCEPT_PAGE_FAULT
2583 SetLastError(STATUS_ACCESS_VIOLATION);
2584 ret = FALSE;
2586 __ENDTRY
2587 return ret;
2590 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2591 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2592 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2594 BOOL ret;
2596 __TRY
2598 struct AsnDecodeSequenceItem items[] = {
2599 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2600 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2601 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2602 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2603 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2606 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2607 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2608 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2610 __EXCEPT_PAGE_FAULT
2612 SetLastError(STATUS_ACCESS_VIOLATION);
2613 ret = FALSE;
2615 __ENDTRY
2616 return ret;
2619 #define RSA1_MAGIC 0x31415352
2621 struct DECODED_RSA_PUB_KEY
2623 DWORD pubexp;
2624 CRYPT_INTEGER_BLOB modulus;
2627 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2628 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2629 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2631 BOOL ret;
2633 __TRY
2635 struct AsnDecodeSequenceItem items[] = {
2636 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2637 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2638 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2639 0 },
2640 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2641 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2643 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2644 DWORD size = 0;
2646 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2647 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2648 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2649 if (ret)
2651 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2652 decodedKey->modulus.cbData;
2654 if (!pvStructInfo)
2656 *pcbStructInfo = bytesNeeded;
2657 ret = TRUE;
2659 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2660 pvStructInfo, pcbStructInfo, bytesNeeded)))
2662 BLOBHEADER *hdr;
2663 RSAPUBKEY *rsaPubKey;
2665 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2666 pvStructInfo = *(BYTE **)pvStructInfo;
2667 hdr = (BLOBHEADER *)pvStructInfo;
2668 hdr->bType = PUBLICKEYBLOB;
2669 hdr->bVersion = CUR_BLOB_VERSION;
2670 hdr->reserved = 0;
2671 hdr->aiKeyAlg = CALG_RSA_KEYX;
2672 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2673 sizeof(BLOBHEADER));
2674 rsaPubKey->magic = RSA1_MAGIC;
2675 rsaPubKey->pubexp = decodedKey->pubexp;
2676 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2677 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2678 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2679 decodedKey->modulus.cbData);
2681 LocalFree(decodedKey);
2684 __EXCEPT_PAGE_FAULT
2686 SetLastError(STATUS_ACCESS_VIOLATION);
2687 ret = FALSE;
2689 __ENDTRY
2690 return ret;
2693 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2694 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2695 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2697 BOOL ret;
2698 DWORD bytesNeeded, dataLen;
2700 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2701 pDecodePara, pvStructInfo, *pcbStructInfo);
2703 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2705 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2706 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2707 else
2708 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2709 if (!pvStructInfo)
2710 *pcbStructInfo = bytesNeeded;
2711 else if (*pcbStructInfo < bytesNeeded)
2713 SetLastError(ERROR_MORE_DATA);
2714 *pcbStructInfo = bytesNeeded;
2715 ret = FALSE;
2717 else
2719 CRYPT_DATA_BLOB *blob;
2720 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2722 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2723 blob->cbData = dataLen;
2724 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2725 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2726 else
2728 assert(blob->pbData);
2729 if (blob->cbData)
2730 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2731 blob->cbData);
2735 return ret;
2738 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2739 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2740 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2742 BOOL ret;
2744 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2745 pDecodePara, pvStructInfo, *pcbStructInfo);
2747 __TRY
2749 DWORD bytesNeeded;
2751 if (!cbEncoded)
2753 SetLastError(CRYPT_E_ASN1_CORRUPT);
2754 ret = FALSE;
2756 else if (pbEncoded[0] != ASN_OCTETSTRING)
2758 SetLastError(CRYPT_E_ASN1_BADTAG);
2759 ret = FALSE;
2761 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2762 lpszStructType, pbEncoded, cbEncoded,
2763 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2765 if (!pvStructInfo)
2766 *pcbStructInfo = bytesNeeded;
2767 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2768 pvStructInfo, pcbStructInfo, bytesNeeded)))
2770 CRYPT_DATA_BLOB *blob;
2772 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2773 pvStructInfo = *(BYTE **)pvStructInfo;
2774 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2775 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2776 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2777 lpszStructType, pbEncoded, cbEncoded,
2778 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2779 &bytesNeeded);
2783 __EXCEPT_PAGE_FAULT
2785 SetLastError(STATUS_ACCESS_VIOLATION);
2786 ret = FALSE;
2788 __ENDTRY
2789 return ret;
2792 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2793 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2794 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2796 BOOL ret;
2798 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2799 pDecodePara, pvStructInfo, *pcbStructInfo);
2801 if (pbEncoded[0] == ASN_BITSTRING)
2803 DWORD bytesNeeded, dataLen;
2805 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2807 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2808 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2809 else
2810 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2811 if (!pvStructInfo)
2812 *pcbStructInfo = bytesNeeded;
2813 else if (*pcbStructInfo < bytesNeeded)
2815 *pcbStructInfo = bytesNeeded;
2816 SetLastError(ERROR_MORE_DATA);
2817 ret = FALSE;
2819 else
2821 CRYPT_BIT_BLOB *blob;
2823 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2824 blob->cbData = dataLen - 1;
2825 blob->cUnusedBits = *(pbEncoded + 1 +
2826 GET_LEN_BYTES(pbEncoded[1]));
2827 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2829 blob->pbData = (BYTE *)pbEncoded + 2 +
2830 GET_LEN_BYTES(pbEncoded[1]);
2832 else
2834 assert(blob->pbData);
2835 if (blob->cbData)
2837 BYTE mask = 0xff << blob->cUnusedBits;
2839 memcpy(blob->pbData, pbEncoded + 2 +
2840 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2841 blob->pbData[blob->cbData - 1] &= mask;
2847 else
2849 SetLastError(CRYPT_E_ASN1_BADTAG);
2850 ret = FALSE;
2852 TRACE("returning %d (%08x)\n", ret, GetLastError());
2853 return ret;
2856 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2857 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2858 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2860 BOOL ret;
2862 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2863 pDecodePara, pvStructInfo, pcbStructInfo);
2865 __TRY
2867 DWORD bytesNeeded;
2869 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2870 lpszStructType, pbEncoded, cbEncoded,
2871 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2873 if (!pvStructInfo)
2874 *pcbStructInfo = bytesNeeded;
2875 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2876 pvStructInfo, pcbStructInfo, bytesNeeded)))
2878 CRYPT_BIT_BLOB *blob;
2880 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2881 pvStructInfo = *(BYTE **)pvStructInfo;
2882 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2883 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2884 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2885 lpszStructType, pbEncoded, cbEncoded,
2886 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2887 &bytesNeeded);
2891 __EXCEPT_PAGE_FAULT
2893 SetLastError(STATUS_ACCESS_VIOLATION);
2894 ret = FALSE;
2896 __ENDTRY
2897 TRACE("returning %d (%08x)\n", ret, GetLastError());
2898 return ret;
2901 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2902 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2903 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2905 BOOL ret;
2907 if (!pvStructInfo)
2909 *pcbStructInfo = sizeof(int);
2910 return TRUE;
2912 __TRY
2914 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2915 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2916 DWORD size = sizeof(buf);
2918 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2919 if (pbEncoded[0] != ASN_INTEGER)
2921 SetLastError(CRYPT_E_ASN1_BADTAG);
2922 ret = FALSE;
2924 else
2925 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2926 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
2927 &size);
2928 if (ret)
2930 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2931 pvStructInfo, pcbStructInfo, sizeof(int))))
2933 int val, i;
2935 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2936 pvStructInfo = *(BYTE **)pvStructInfo;
2937 if (blob->pbData[blob->cbData - 1] & 0x80)
2939 /* initialize to a negative value to sign-extend */
2940 val = -1;
2942 else
2943 val = 0;
2944 for (i = 0; i < blob->cbData; i++)
2946 val <<= 8;
2947 val |= blob->pbData[blob->cbData - i - 1];
2949 memcpy(pvStructInfo, &val, sizeof(int));
2952 else if (GetLastError() == ERROR_MORE_DATA)
2953 SetLastError(CRYPT_E_ASN1_LARGE);
2955 __EXCEPT_PAGE_FAULT
2957 SetLastError(STATUS_ACCESS_VIOLATION);
2958 ret = FALSE;
2960 __ENDTRY
2961 return ret;
2964 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2965 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2966 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2968 BOOL ret;
2969 DWORD bytesNeeded, dataLen;
2971 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2973 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2975 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2976 if (!pvStructInfo)
2977 *pcbStructInfo = bytesNeeded;
2978 else if (*pcbStructInfo < bytesNeeded)
2980 *pcbStructInfo = bytesNeeded;
2981 SetLastError(ERROR_MORE_DATA);
2982 ret = FALSE;
2984 else
2986 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2988 blob->cbData = dataLen;
2989 assert(blob->pbData);
2990 if (blob->cbData)
2992 DWORD i;
2994 for (i = 0; i < blob->cbData; i++)
2996 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2997 dataLen - i - 1);
3002 return ret;
3005 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3006 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3007 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3009 BOOL ret;
3011 __TRY
3013 DWORD bytesNeeded;
3015 if (pbEncoded[0] != ASN_INTEGER)
3017 SetLastError(CRYPT_E_ASN1_BADTAG);
3018 ret = FALSE;
3020 else
3021 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3022 lpszStructType, pbEncoded, cbEncoded,
3023 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
3024 if (ret)
3026 if (!pvStructInfo)
3027 *pcbStructInfo = bytesNeeded;
3028 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3029 pvStructInfo, pcbStructInfo, bytesNeeded)))
3031 CRYPT_INTEGER_BLOB *blob;
3033 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3034 pvStructInfo = *(BYTE **)pvStructInfo;
3035 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3036 blob->pbData = (BYTE *)pvStructInfo +
3037 sizeof(CRYPT_INTEGER_BLOB);
3038 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3039 lpszStructType, pbEncoded, cbEncoded,
3040 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3041 &bytesNeeded);
3045 __EXCEPT_PAGE_FAULT
3047 SetLastError(STATUS_ACCESS_VIOLATION);
3048 ret = FALSE;
3050 __ENDTRY
3051 return ret;
3054 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
3055 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3056 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3057 void *pvStructInfo, DWORD *pcbStructInfo)
3059 BOOL ret;
3061 if (pbEncoded[0] == ASN_INTEGER)
3063 DWORD bytesNeeded, dataLen;
3065 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3067 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3069 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3070 if (!pvStructInfo)
3071 *pcbStructInfo = bytesNeeded;
3072 else if (*pcbStructInfo < bytesNeeded)
3074 *pcbStructInfo = bytesNeeded;
3075 SetLastError(ERROR_MORE_DATA);
3076 ret = FALSE;
3078 else
3080 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3082 blob->cbData = dataLen;
3083 assert(blob->pbData);
3084 /* remove leading zero byte if it exists */
3085 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3087 blob->cbData--;
3088 blob->pbData++;
3090 if (blob->cbData)
3092 DWORD i;
3094 for (i = 0; i < blob->cbData; i++)
3096 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3097 dataLen - i - 1);
3103 else
3105 SetLastError(CRYPT_E_ASN1_BADTAG);
3106 ret = FALSE;
3108 return ret;
3111 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3112 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3113 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3115 BOOL ret;
3117 __TRY
3119 DWORD bytesNeeded;
3121 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3122 lpszStructType, pbEncoded, cbEncoded,
3123 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
3125 if (!pvStructInfo)
3126 *pcbStructInfo = bytesNeeded;
3127 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3128 pvStructInfo, pcbStructInfo, bytesNeeded)))
3130 CRYPT_INTEGER_BLOB *blob;
3132 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3133 pvStructInfo = *(BYTE **)pvStructInfo;
3134 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3135 blob->pbData = (BYTE *)pvStructInfo +
3136 sizeof(CRYPT_INTEGER_BLOB);
3137 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3138 lpszStructType, pbEncoded, cbEncoded,
3139 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3140 &bytesNeeded);
3144 __EXCEPT_PAGE_FAULT
3146 SetLastError(STATUS_ACCESS_VIOLATION);
3147 ret = FALSE;
3149 __ENDTRY
3150 return ret;
3153 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3154 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3155 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3157 BOOL ret;
3159 if (!pvStructInfo)
3161 *pcbStructInfo = sizeof(int);
3162 return TRUE;
3164 __TRY
3166 if (pbEncoded[0] == ASN_ENUMERATED)
3168 unsigned int val = 0, i;
3170 if (cbEncoded <= 1)
3172 SetLastError(CRYPT_E_ASN1_EOD);
3173 ret = FALSE;
3175 else if (pbEncoded[1] == 0)
3177 SetLastError(CRYPT_E_ASN1_CORRUPT);
3178 ret = FALSE;
3180 else
3182 /* A little strange looking, but we have to accept a sign byte:
3183 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3184 * assuming a small length is okay here, it has to be in short
3185 * form.
3187 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3189 SetLastError(CRYPT_E_ASN1_LARGE);
3190 return FALSE;
3192 for (i = 0; i < pbEncoded[1]; i++)
3194 val <<= 8;
3195 val |= pbEncoded[2 + i];
3197 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3198 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3200 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3201 pvStructInfo = *(BYTE **)pvStructInfo;
3202 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3206 else
3208 SetLastError(CRYPT_E_ASN1_BADTAG);
3209 ret = FALSE;
3212 __EXCEPT_PAGE_FAULT
3214 SetLastError(STATUS_ACCESS_VIOLATION);
3215 ret = FALSE;
3217 __ENDTRY
3218 return ret;
3221 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3222 * if it fails.
3224 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3225 do { \
3226 BYTE i; \
3228 (word) = 0; \
3229 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3231 if (!isdigit(*(pbEncoded))) \
3233 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3234 ret = FALSE; \
3236 else \
3238 (word) *= 10; \
3239 (word) += *(pbEncoded)++ - '0'; \
3242 } while (0)
3244 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3245 SYSTEMTIME *sysTime)
3247 BOOL ret;
3249 __TRY
3251 ret = TRUE;
3252 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3254 WORD hours, minutes = 0;
3255 BYTE sign = *pbEncoded++;
3257 len--;
3258 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3259 if (ret && hours >= 24)
3261 SetLastError(CRYPT_E_ASN1_CORRUPT);
3262 ret = FALSE;
3264 else if (len >= 2)
3266 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3267 if (ret && minutes >= 60)
3269 SetLastError(CRYPT_E_ASN1_CORRUPT);
3270 ret = FALSE;
3273 if (ret)
3275 if (sign == '+')
3277 sysTime->wHour += hours;
3278 sysTime->wMinute += minutes;
3280 else
3282 if (hours > sysTime->wHour)
3284 sysTime->wDay--;
3285 sysTime->wHour = 24 - (hours - sysTime->wHour);
3287 else
3288 sysTime->wHour -= hours;
3289 if (minutes > sysTime->wMinute)
3291 sysTime->wHour--;
3292 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3294 else
3295 sysTime->wMinute -= minutes;
3300 __EXCEPT_PAGE_FAULT
3302 SetLastError(STATUS_ACCESS_VIOLATION);
3303 ret = FALSE;
3305 __ENDTRY
3306 return ret;
3309 #define MIN_ENCODED_TIME_LENGTH 10
3311 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3312 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3313 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3315 BOOL ret;
3317 if (!pvStructInfo)
3319 *pcbStructInfo = sizeof(FILETIME);
3320 return TRUE;
3322 __TRY
3324 ret = TRUE;
3325 if (pbEncoded[0] == ASN_UTCTIME)
3327 if (cbEncoded <= 1)
3329 SetLastError(CRYPT_E_ASN1_EOD);
3330 ret = FALSE;
3332 else if (pbEncoded[1] > 0x7f)
3334 /* long-form date strings really can't be valid */
3335 SetLastError(CRYPT_E_ASN1_CORRUPT);
3336 ret = FALSE;
3338 else
3340 SYSTEMTIME sysTime = { 0 };
3341 BYTE len = pbEncoded[1];
3343 if (len < MIN_ENCODED_TIME_LENGTH)
3345 SetLastError(CRYPT_E_ASN1_CORRUPT);
3346 ret = FALSE;
3348 else
3350 pbEncoded += 2;
3351 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3352 if (sysTime.wYear >= 50)
3353 sysTime.wYear += 1900;
3354 else
3355 sysTime.wYear += 2000;
3356 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3357 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3358 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3359 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3360 if (ret && len > 0)
3362 if (len >= 2 && isdigit(*pbEncoded) &&
3363 isdigit(*(pbEncoded + 1)))
3364 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3365 sysTime.wSecond);
3366 else if (isdigit(*pbEncoded))
3367 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3368 sysTime.wSecond);
3369 if (ret)
3370 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3371 &sysTime);
3373 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3374 pDecodePara, pvStructInfo, pcbStructInfo,
3375 sizeof(FILETIME))))
3377 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3378 pvStructInfo = *(BYTE **)pvStructInfo;
3379 ret = SystemTimeToFileTime(&sysTime,
3380 (FILETIME *)pvStructInfo);
3385 else
3387 SetLastError(CRYPT_E_ASN1_BADTAG);
3388 ret = FALSE;
3391 __EXCEPT_PAGE_FAULT
3393 SetLastError(STATUS_ACCESS_VIOLATION);
3394 ret = FALSE;
3396 __ENDTRY
3397 return ret;
3400 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3401 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3402 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3404 BOOL ret;
3406 if (!pvStructInfo)
3408 *pcbStructInfo = sizeof(FILETIME);
3409 return TRUE;
3411 __TRY
3413 ret = TRUE;
3414 if (pbEncoded[0] == ASN_GENERALTIME)
3416 if (cbEncoded <= 1)
3418 SetLastError(CRYPT_E_ASN1_EOD);
3419 ret = FALSE;
3421 else if (pbEncoded[1] > 0x7f)
3423 /* long-form date strings really can't be valid */
3424 SetLastError(CRYPT_E_ASN1_CORRUPT);
3425 ret = FALSE;
3427 else
3429 BYTE len = pbEncoded[1];
3431 if (len < MIN_ENCODED_TIME_LENGTH)
3433 SetLastError(CRYPT_E_ASN1_CORRUPT);
3434 ret = FALSE;
3436 else
3438 SYSTEMTIME sysTime = { 0 };
3440 pbEncoded += 2;
3441 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3442 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3443 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3444 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3445 if (ret && len > 0)
3447 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3448 sysTime.wMinute);
3449 if (ret && len > 0)
3450 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3451 sysTime.wSecond);
3452 if (ret && len > 0 && (*pbEncoded == '.' ||
3453 *pbEncoded == ','))
3455 BYTE digits;
3457 pbEncoded++;
3458 len--;
3459 /* workaround macro weirdness */
3460 digits = min(len, 3);
3461 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3462 sysTime.wMilliseconds);
3464 if (ret)
3465 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3466 &sysTime);
3468 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3469 pDecodePara, pvStructInfo, pcbStructInfo,
3470 sizeof(FILETIME))))
3472 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3473 pvStructInfo = *(BYTE **)pvStructInfo;
3474 ret = SystemTimeToFileTime(&sysTime,
3475 (FILETIME *)pvStructInfo);
3480 else
3482 SetLastError(CRYPT_E_ASN1_BADTAG);
3483 ret = FALSE;
3486 __EXCEPT_PAGE_FAULT
3488 SetLastError(STATUS_ACCESS_VIOLATION);
3489 ret = FALSE;
3491 __ENDTRY
3492 return ret;
3495 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3496 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3497 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3499 BOOL ret;
3501 __TRY
3503 if (pbEncoded[0] == ASN_UTCTIME)
3504 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3505 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3506 pcbStructInfo);
3507 else if (pbEncoded[0] == ASN_GENERALTIME)
3508 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3509 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3510 pvStructInfo, pcbStructInfo);
3511 else
3513 SetLastError(CRYPT_E_ASN1_BADTAG);
3514 ret = FALSE;
3517 __EXCEPT_PAGE_FAULT
3519 SetLastError(STATUS_ACCESS_VIOLATION);
3520 ret = FALSE;
3522 __ENDTRY
3523 return ret;
3526 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3527 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3528 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3530 BOOL ret = TRUE;
3532 __TRY
3534 if (pbEncoded[0] == ASN_SEQUENCEOF)
3536 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3538 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3540 BYTE lenBytes;
3541 const BYTE *ptr;
3543 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3544 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3545 cValue = 0;
3546 ptr = pbEncoded + 1 + lenBytes;
3547 remainingLen = dataLen;
3548 while (ret && remainingLen)
3550 DWORD nextLen;
3552 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3553 if (ret)
3555 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3557 remainingLen -= 1 + nextLenBytes + nextLen;
3558 ptr += 1 + nextLenBytes + nextLen;
3559 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3560 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3561 bytesNeeded += 1 + nextLenBytes + nextLen;
3562 cValue++;
3565 if (ret)
3567 CRYPT_SEQUENCE_OF_ANY *seq;
3568 BYTE *nextPtr;
3569 DWORD i;
3571 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3572 pvStructInfo, pcbStructInfo, bytesNeeded)))
3574 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3575 pvStructInfo = *(BYTE **)pvStructInfo;
3576 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3577 seq->cValue = cValue;
3578 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3579 sizeof(*seq));
3580 nextPtr = (BYTE *)seq->rgValue +
3581 cValue * sizeof(CRYPT_DER_BLOB);
3582 ptr = pbEncoded + 1 + lenBytes;
3583 remainingLen = dataLen;
3584 i = 0;
3585 while (ret && remainingLen)
3587 DWORD nextLen;
3589 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3590 if (ret)
3592 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3594 seq->rgValue[i].cbData = 1 + nextLenBytes +
3595 nextLen;
3596 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3597 seq->rgValue[i].pbData = (BYTE *)ptr;
3598 else
3600 seq->rgValue[i].pbData = nextPtr;
3601 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3602 nextLen);
3603 nextPtr += 1 + nextLenBytes + nextLen;
3605 remainingLen -= 1 + nextLenBytes + nextLen;
3606 ptr += 1 + nextLenBytes + nextLen;
3607 i++;
3614 else
3616 SetLastError(CRYPT_E_ASN1_BADTAG);
3617 ret = FALSE;
3620 __EXCEPT_PAGE_FAULT
3622 SetLastError(STATUS_ACCESS_VIOLATION);
3623 ret = FALSE;
3625 __ENDTRY
3626 return ret;
3629 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3630 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3631 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3633 BOOL ret;
3635 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3637 DWORD bytesNeeded, dataLen;
3639 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3641 struct AsnArrayDescriptor arrayDesc = {
3642 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3643 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3644 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3645 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3647 if (dataLen)
3649 DWORD nameLen;
3651 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3652 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3653 0, NULL, NULL, &nameLen, NULL);
3654 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3656 else
3657 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3658 if (!pvStructInfo)
3659 *pcbStructInfo = bytesNeeded;
3660 else if (*pcbStructInfo < bytesNeeded)
3662 *pcbStructInfo = bytesNeeded;
3663 SetLastError(ERROR_MORE_DATA);
3664 ret = FALSE;
3666 else
3668 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3670 if (dataLen)
3672 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3673 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3674 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3675 0, NULL, &name->u.FullName, pcbStructInfo,
3676 name->u.FullName.rgAltEntry);
3678 else
3679 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3683 else
3685 SetLastError(CRYPT_E_ASN1_BADTAG);
3686 ret = FALSE;
3688 return ret;
3691 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3692 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3693 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3695 struct AsnDecodeSequenceItem items[] = {
3696 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3697 DistPointName), CRYPT_AsnDecodeDistPointName,
3698 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3699 DistPointName.u.FullName.rgAltEntry), 0 },
3700 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3701 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3702 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3703 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3704 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3705 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3707 BOOL ret;
3709 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3710 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3711 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3712 return ret;
3715 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3716 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3717 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3719 BOOL ret;
3721 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3722 pDecodePara, pvStructInfo, *pcbStructInfo);
3724 __TRY
3726 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3727 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3728 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3730 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3731 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3733 __EXCEPT_PAGE_FAULT
3735 SetLastError(STATUS_ACCESS_VIOLATION);
3736 ret = FALSE;
3738 __ENDTRY
3739 return ret;
3742 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3743 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3744 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3746 BOOL ret;
3748 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3749 pDecodePara, pvStructInfo, *pcbStructInfo);
3751 __TRY
3753 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3754 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3756 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3757 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3759 __EXCEPT_PAGE_FAULT
3761 SetLastError(STATUS_ACCESS_VIOLATION);
3762 ret = FALSE;
3764 __ENDTRY
3765 return ret;
3768 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3769 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3770 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3772 BOOL ret;
3774 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3775 pDecodePara, pvStructInfo, *pcbStructInfo);
3777 __TRY
3779 struct AsnDecodeSequenceItem items[] = {
3780 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3781 DistPointName), CRYPT_AsnDecodeDistPointName,
3782 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3783 offsetof(CRL_ISSUING_DIST_POINT,
3784 DistPointName.u.FullName.rgAltEntry), 0 },
3785 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3786 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3787 FALSE, 0 },
3788 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3789 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3790 FALSE, 0 },
3791 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3792 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3793 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3794 OnlySomeReasonFlags.pbData), 0 },
3795 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3796 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3799 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3800 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3801 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3803 __EXCEPT_PAGE_FAULT
3805 SetLastError(STATUS_ACCESS_VIOLATION);
3806 ret = FALSE;
3808 __ENDTRY
3809 return ret;
3812 static BOOL WINAPI CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType,
3813 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3814 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3816 BOOL ret;
3817 struct AsnDecodeSequenceItem items[] = {
3818 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
3819 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
3820 Issuer.pbData) },
3821 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
3822 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
3823 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
3825 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3826 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3828 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3829 pDecodePara, pvStructInfo, *pcbStructInfo);
3831 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3832 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3833 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
3834 issuerSerial ? issuerSerial->Issuer.pbData : NULL);
3835 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
3837 SetLastError(CRYPT_E_ASN1_CORRUPT);
3838 ret = FALSE;
3840 TRACE("returning %d\n", ret);
3841 return ret;
3844 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfoInternal(
3845 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3846 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3847 void *pvStructInfo, DWORD *pcbStructInfo)
3849 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
3850 struct AsnDecodeSequenceItem items[] = {
3851 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
3852 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3853 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
3854 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
3855 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
3856 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
3857 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3858 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
3859 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
3860 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
3861 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3862 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
3863 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
3864 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3865 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
3866 HashEncryptionAlgorithm.pszObjId), 0 },
3867 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
3868 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
3869 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
3870 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
3871 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
3872 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3873 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
3875 BOOL ret;
3877 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3878 pDecodePara, pvStructInfo, *pcbStructInfo);
3880 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3881 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3882 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
3883 info ? info->Issuer.pbData : NULL);
3884 return ret;
3887 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
3888 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3889 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3891 BOOL ret = FALSE;
3893 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3894 pDecodePara, pvStructInfo, *pcbStructInfo);
3896 __TRY
3898 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType,
3899 lpszStructType, pbEncoded, cbEncoded,
3900 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
3901 if (ret && pvStructInfo)
3903 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3904 pcbStructInfo, *pcbStructInfo);
3905 if (ret)
3907 CMSG_SIGNER_INFO *info;
3909 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3910 pvStructInfo = *(BYTE **)pvStructInfo;
3911 info = (CMSG_SIGNER_INFO *)pvStructInfo;
3912 info->Issuer.pbData = ((BYTE *)info +
3913 sizeof(CMSG_SIGNER_INFO));
3914 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType,
3915 lpszStructType, pbEncoded, cbEncoded,
3916 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
3917 pcbStructInfo);
3921 __EXCEPT_PAGE_FAULT
3923 SetLastError(STATUS_ACCESS_VIOLATION);
3925 __ENDTRY
3926 TRACE("returning %d\n", ret);
3927 return ret;
3930 static BOOL WINAPI CRYPT_DecodeSignerArray(DWORD dwCertEncodingType,
3931 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3932 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3934 BOOL ret;
3935 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
3936 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
3937 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
3938 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
3940 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3941 pDecodePara, pvStructInfo, *pcbStructInfo);
3943 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3944 pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
3945 return ret;
3948 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
3949 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3950 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
3952 BOOL ret = FALSE;
3953 struct AsnDecodeSequenceItem items[] = {
3954 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version), CRYPT_AsnDecodeInt,
3955 sizeof(DWORD), FALSE, FALSE, 0, 0 },
3956 /* Placeholder for the hash algorithms - redundant with those in the
3957 * signers, so just ignore them.
3959 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
3960 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
3961 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
3962 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
3963 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
3964 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
3965 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
3966 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
3967 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
3968 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
3969 sizeof(struct GenericArray), TRUE, TRUE,
3970 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
3971 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
3972 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
3973 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
3976 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3977 pDecodePara, signedInfo, *pcbSignedInfo);
3979 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3980 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
3981 pDecodePara, signedInfo, pcbSignedInfo, NULL);
3982 TRACE("returning %d\n", ret);
3983 return ret;
3986 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
3987 LPCSTR lpszStructType)
3989 CryptDecodeObjectExFunc decodeFunc = NULL;
3991 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3992 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3994 SetLastError(ERROR_FILE_NOT_FOUND);
3995 return NULL;
3997 if (!HIWORD(lpszStructType))
3999 switch (LOWORD(lpszStructType))
4001 case (WORD)X509_CERT:
4002 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4003 break;
4004 case (WORD)X509_CERT_TO_BE_SIGNED:
4005 decodeFunc = CRYPT_AsnDecodeCert;
4006 break;
4007 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
4008 decodeFunc = CRYPT_AsnDecodeCRL;
4009 break;
4010 case (WORD)X509_EXTENSIONS:
4011 decodeFunc = CRYPT_AsnDecodeExtensions;
4012 break;
4013 case (WORD)X509_NAME_VALUE:
4014 decodeFunc = CRYPT_AsnDecodeNameValue;
4015 break;
4016 case (WORD)X509_NAME:
4017 decodeFunc = CRYPT_AsnDecodeName;
4018 break;
4019 case (WORD)X509_PUBLIC_KEY_INFO:
4020 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4021 break;
4022 case (WORD)X509_AUTHORITY_KEY_ID:
4023 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4024 break;
4025 case (WORD)X509_ALTERNATE_NAME:
4026 decodeFunc = CRYPT_AsnDecodeAltName;
4027 break;
4028 case (WORD)X509_BASIC_CONSTRAINTS:
4029 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4030 break;
4031 case (WORD)X509_BASIC_CONSTRAINTS2:
4032 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4033 break;
4034 case (WORD)RSA_CSP_PUBLICKEYBLOB:
4035 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4036 break;
4037 case (WORD)X509_UNICODE_NAME:
4038 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4039 break;
4040 case (WORD)PKCS_ATTRIBUTE:
4041 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4042 break;
4043 case (WORD)X509_UNICODE_NAME_VALUE:
4044 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4045 break;
4046 case (WORD)X509_OCTET_STRING:
4047 decodeFunc = CRYPT_AsnDecodeOctets;
4048 break;
4049 case (WORD)X509_BITS:
4050 case (WORD)X509_KEY_USAGE:
4051 decodeFunc = CRYPT_AsnDecodeBits;
4052 break;
4053 case (WORD)X509_INTEGER:
4054 decodeFunc = CRYPT_AsnDecodeInt;
4055 break;
4056 case (WORD)X509_MULTI_BYTE_INTEGER:
4057 decodeFunc = CRYPT_AsnDecodeInteger;
4058 break;
4059 case (WORD)X509_MULTI_BYTE_UINT:
4060 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4061 break;
4062 case (WORD)X509_ENUMERATED:
4063 decodeFunc = CRYPT_AsnDecodeEnumerated;
4064 break;
4065 case (WORD)X509_CHOICE_OF_TIME:
4066 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4067 break;
4068 case (WORD)X509_AUTHORITY_KEY_ID2:
4069 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4070 break;
4071 case (WORD)PKCS_CONTENT_INFO:
4072 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4073 break;
4074 case (WORD)X509_SEQUENCE_OF_ANY:
4075 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4076 break;
4077 case (WORD)PKCS_UTC_TIME:
4078 decodeFunc = CRYPT_AsnDecodeUtcTime;
4079 break;
4080 case (WORD)X509_CRL_DIST_POINTS:
4081 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4082 break;
4083 case (WORD)X509_ENHANCED_KEY_USAGE:
4084 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4085 break;
4086 case (WORD)PKCS_ATTRIBUTES:
4087 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4088 break;
4089 case (WORD)X509_ISSUING_DIST_POINT:
4090 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4091 break;
4092 case (WORD)PKCS7_SIGNER_INFO:
4093 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4094 break;
4097 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4098 decodeFunc = CRYPT_AsnDecodeExtensions;
4099 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4100 decodeFunc = CRYPT_AsnDecodeUtcTime;
4101 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4102 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4103 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4104 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4105 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4106 decodeFunc = CRYPT_AsnDecodeEnumerated;
4107 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4108 decodeFunc = CRYPT_AsnDecodeBits;
4109 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4110 decodeFunc = CRYPT_AsnDecodeOctets;
4111 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4112 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4113 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4114 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4115 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4116 decodeFunc = CRYPT_AsnDecodeAltName;
4117 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4118 decodeFunc = CRYPT_AsnDecodeAltName;
4119 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4120 decodeFunc = CRYPT_AsnDecodeAltName;
4121 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4122 decodeFunc = CRYPT_AsnDecodeAltName;
4123 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4124 decodeFunc = CRYPT_AsnDecodeAltName;
4125 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4126 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4127 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4128 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4129 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4130 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4131 return decodeFunc;
4134 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4135 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4137 static HCRYPTOIDFUNCSET set = NULL;
4138 CryptDecodeObjectFunc decodeFunc = NULL;
4140 if (!set)
4141 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4142 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4143 (void **)&decodeFunc, hFunc);
4144 return decodeFunc;
4147 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4148 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4150 static HCRYPTOIDFUNCSET set = NULL;
4151 CryptDecodeObjectExFunc decodeFunc = NULL;
4153 if (!set)
4154 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4155 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4156 (void **)&decodeFunc, hFunc);
4157 return decodeFunc;
4160 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4161 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4162 DWORD *pcbStructInfo)
4164 BOOL ret = FALSE;
4165 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4166 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4167 HCRYPTOIDFUNCADDR hFunc = NULL;
4169 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4170 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4171 pvStructInfo, pcbStructInfo);
4173 if (!pvStructInfo && !pcbStructInfo)
4175 SetLastError(ERROR_INVALID_PARAMETER);
4176 return FALSE;
4178 if (!cbEncoded)
4180 SetLastError(CRYPT_E_ASN1_EOD);
4181 return FALSE;
4183 if (cbEncoded > MAX_ENCODED_LEN)
4185 SetLastError(CRYPT_E_ASN1_LARGE);
4186 return FALSE;
4189 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4190 lpszStructType)))
4192 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4193 debugstr_a(lpszStructType));
4194 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4195 lpszStructType, &hFunc);
4196 if (!pCryptDecodeObject)
4197 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4198 lpszStructType, &hFunc);
4200 if (pCryptDecodeObject)
4201 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4202 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4203 else if (pCryptDecodeObjectEx)
4204 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4205 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4206 pvStructInfo, pcbStructInfo);
4207 if (hFunc)
4208 CryptFreeOIDFunctionAddress(hFunc, 0);
4209 TRACE_(crypt)("returning %d\n", ret);
4210 return ret;
4213 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4214 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4215 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4217 BOOL ret = FALSE;
4218 CryptDecodeObjectExFunc decodeFunc;
4219 HCRYPTOIDFUNCADDR hFunc = NULL;
4221 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4222 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4223 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4225 if (!pvStructInfo && !pcbStructInfo)
4227 SetLastError(ERROR_INVALID_PARAMETER);
4228 return FALSE;
4230 if (!cbEncoded)
4232 SetLastError(CRYPT_E_ASN1_EOD);
4233 return FALSE;
4235 if (cbEncoded > MAX_ENCODED_LEN)
4237 SetLastError(CRYPT_E_ASN1_LARGE);
4238 return FALSE;
4241 SetLastError(NOERROR);
4242 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4243 *(BYTE **)pvStructInfo = NULL;
4244 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4245 if (!decodeFunc)
4247 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4248 debugstr_a(lpszStructType));
4249 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4250 &hFunc);
4252 if (decodeFunc)
4253 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4254 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4255 else
4257 CryptDecodeObjectFunc pCryptDecodeObject =
4258 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4260 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4261 * directly, as that could cause an infinite loop.
4263 if (pCryptDecodeObject)
4265 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4267 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4268 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4269 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4270 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4271 ret = pCryptDecodeObject(dwCertEncodingType,
4272 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4273 *(BYTE **)pvStructInfo, pcbStructInfo);
4275 else
4276 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4277 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4280 if (hFunc)
4281 CryptFreeOIDFunctionAddress(hFunc, 0);
4282 TRACE_(crypt)("returning %d\n", ret);
4283 return ret;