push 4d5485f9b89f417d46b39b93e8d940437007f325
[wine/hacks.git] / dlls / crypt32 / decode.c
blob723873ac9fe29591ef672d9a83b40f7d3a8c2d19
1 /*
2 * Copyright 2005 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 is
21 * undocumented, 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:
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
34 #include <assert.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
39 #define NONAMELESSUNION
41 #include "windef.h"
42 #include "winbase.h"
43 #include "wincrypt.h"
44 #include "winnls.h"
45 #include "snmp.h"
46 #include "wine/debug.h"
47 #include "wine/exception.h"
48 #include "crypt32_private.h"
50 /* This is a bit arbitrary, but to set some limit: */
51 #define MAX_ENCODED_LEN 0x02000000
53 #define ASN_FLAGS_MASK 0xe0
54 #define ASN_TYPE_MASK 0x1f
56 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
57 WINE_DECLARE_DEBUG_CHANNEL(crypt);
59 struct GenericArray
61 DWORD cItems;
62 BYTE *rgItems;
65 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
66 DWORD, DWORD, void *, DWORD *);
67 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
68 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
70 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
71 * The dwCertEncodingType and lpszStructType are ignored by the built-in
72 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
73 * since it must call functions in external DLLs that follow these signatures.
75 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
77 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
78 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
80 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
81 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
82 * time, doesn't do memory allocation, and doesn't do exception handling.
83 * (This isn't intended to be the externally-called one.)
85 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
86 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
87 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
88 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
89 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
90 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
91 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
92 /* Internal function */
93 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
94 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
95 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
96 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
97 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
98 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
99 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
100 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
101 * member has been initialized, doesn't do exception handling, and doesn't do
102 * memory allocation.
104 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
105 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
106 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
107 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
108 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
109 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
110 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
111 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
112 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
113 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
114 * member has been initialized, doesn't do exception handling, and doesn't do
115 * memory allocation. Also doesn't check tag, assumes the caller has checked
116 * it.
118 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
119 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
120 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
121 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
122 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
123 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
124 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
125 void *pvStructInfo, DWORD *pcbStructInfo);
127 /* Gets the number of length bytes from the given (leading) length byte */
128 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
130 /* Helper function to get the encoded length of the data starting at pbEncoded,
131 * where pbEncoded[0] is the tag. If the data are too short to contain a
132 * length or if the length is too large for cbEncoded, sets an appropriate
133 * error code and returns FALSE.
135 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
136 DWORD *len)
138 BOOL ret;
140 if (cbEncoded <= 1)
142 SetLastError(CRYPT_E_ASN1_CORRUPT);
143 ret = FALSE;
145 else if (pbEncoded[1] <= 0x7f)
147 if (pbEncoded[1] + 1 > cbEncoded)
149 SetLastError(CRYPT_E_ASN1_EOD);
150 ret = FALSE;
152 else
154 *len = pbEncoded[1];
155 ret = TRUE;
158 else if (pbEncoded[1] == 0x80)
160 FIXME("unimplemented for indefinite-length encoding\n");
161 SetLastError(CRYPT_E_ASN1_CORRUPT);
162 ret = FALSE;
164 else
166 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
168 if (lenLen > sizeof(DWORD) + 1)
170 SetLastError(CRYPT_E_ASN1_LARGE);
171 ret = FALSE;
173 else if (lenLen + 2 > cbEncoded)
175 SetLastError(CRYPT_E_ASN1_CORRUPT);
176 ret = FALSE;
178 else
180 DWORD out = 0;
182 pbEncoded += 2;
183 while (--lenLen)
185 out <<= 8;
186 out |= *pbEncoded++;
188 if (out + lenLen + 1 > cbEncoded)
190 SetLastError(CRYPT_E_ASN1_EOD);
191 ret = FALSE;
193 else
195 *len = out;
196 ret = TRUE;
200 return ret;
203 /* Helper function to check *pcbStructInfo, set it to the required size, and
204 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
205 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
206 * pointer to the newly allocated memory.
208 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
209 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
210 DWORD bytesNeeded)
212 BOOL ret = TRUE;
214 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
216 if (pDecodePara && pDecodePara->pfnAlloc)
217 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
218 else
219 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
220 if (!*(BYTE **)pvStructInfo)
221 ret = FALSE;
222 else
223 *pcbStructInfo = bytesNeeded;
225 else if (*pcbStructInfo < bytesNeeded)
227 *pcbStructInfo = bytesNeeded;
228 SetLastError(ERROR_MORE_DATA);
229 ret = FALSE;
231 return ret;
234 /* tag:
235 * The expected tag of the item. If tag is 0, decodeFunc is called
236 * regardless of the tag value seen.
237 * offset:
238 * A sequence is decoded into a struct. The offset member is the
239 * offset of this item within that struct.
240 * decodeFunc:
241 * The decoder function to use. If this is NULL, then the member isn't
242 * decoded, but minSize space is reserved for it.
243 * minSize:
244 * The minimum amount of space occupied after decoding. You must set this.
245 * optional:
246 * If true, and the tag doesn't match the expected tag for this item,
247 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
248 * filled with 0 for this member.
249 * hasPointer, pointerOffset:
250 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
251 * the offset within the struct of the data pointer (or to the
252 * first data pointer, if more than one exist).
253 * size:
254 * Used by CRYPT_AsnDecodeSequence, not for your use.
256 struct AsnDecodeSequenceItem
258 BYTE tag;
259 DWORD offset;
260 CryptDecodeObjectExFunc decodeFunc;
261 DWORD minSize;
262 BOOL optional;
263 BOOL hasPointer;
264 DWORD pointerOffset;
265 DWORD size;
268 /* Decodes the items in a sequence, where the items are described in items,
269 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
270 * pvStructInfo. nextData is a pointer to the memory location at which the
271 * first decoded item with a dynamic pointer should point.
272 * Upon decoding, *cbDecoded is the total number of bytes decoded.
274 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
275 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
276 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
277 DWORD *cbDecoded)
279 BOOL ret;
280 DWORD i, decoded = 0;
281 const BYTE *ptr = pbEncoded;
283 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
284 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
286 for (i = 0, ret = TRUE; ret && i < cItem; i++)
288 if (cbEncoded - (ptr - pbEncoded) != 0)
290 DWORD nextItemLen;
292 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
293 &nextItemLen)))
295 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
297 if (ptr[0] == items[i].tag || !items[i].tag)
299 if (nextData && pvStructInfo && items[i].hasPointer)
301 TRACE("Setting next pointer to %p\n",
302 nextData);
303 *(BYTE **)((BYTE *)pvStructInfo +
304 items[i].pointerOffset) = nextData;
306 if (items[i].decodeFunc)
308 if (pvStructInfo)
309 TRACE("decoding item %d\n", i);
310 else
311 TRACE("sizing item %d\n", i);
312 ret = items[i].decodeFunc(dwCertEncodingType,
313 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
314 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
315 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
316 : NULL, &items[i].size);
317 if (ret)
319 /* Account for alignment padding */
320 if (items[i].size % sizeof(DWORD))
321 items[i].size += sizeof(DWORD) -
322 items[i].size % sizeof(DWORD);
323 TRACE("item %d size: %d\n", i, items[i].size);
324 if (nextData && items[i].hasPointer &&
325 items[i].size > items[i].minSize)
326 nextData += items[i].size - items[i].minSize;
327 ptr += 1 + nextItemLenBytes + nextItemLen;
328 decoded += 1 + nextItemLenBytes + nextItemLen;
329 TRACE("item %d: decoded %d bytes\n", i,
330 1 + nextItemLenBytes + nextItemLen);
332 else if (items[i].optional &&
333 GetLastError() == CRYPT_E_ASN1_BADTAG)
335 TRACE("skipping optional item %d\n", i);
336 items[i].size = items[i].minSize;
337 SetLastError(NOERROR);
338 ret = TRUE;
340 else
341 TRACE("item %d failed: %08x\n", i,
342 GetLastError());
344 else
346 TRACE("item %d: decoded %d bytes\n", i,
347 1 + nextItemLenBytes + nextItemLen);
348 ptr += 1 + nextItemLenBytes + nextItemLen;
349 decoded += 1 + nextItemLenBytes + nextItemLen;
350 items[i].size = items[i].minSize;
353 else if (items[i].optional)
355 TRACE("skipping optional item %d\n", i);
356 items[i].size = items[i].minSize;
358 else
360 TRACE("item %d: tag %02x doesn't match expected %02x\n",
361 i, ptr[0], items[i].tag);
362 SetLastError(CRYPT_E_ASN1_BADTAG);
363 ret = FALSE;
367 else if (items[i].optional)
369 TRACE("missing optional item %d, skipping\n", i);
370 items[i].size = items[i].minSize;
372 else
374 TRACE("not enough bytes for item %d, failing\n", i);
375 SetLastError(CRYPT_E_ASN1_CORRUPT);
376 ret = FALSE;
379 if (ret)
380 *cbDecoded = decoded;
381 TRACE("returning %d\n", ret);
382 return ret;
385 /* This decodes an arbitrary sequence into a contiguous block of memory
386 * (basically, a struct.) Each element being decoded is described by a struct
387 * AsnDecodeSequenceItem, see above.
388 * startingPointer is an optional pointer to the first place where dynamic
389 * data will be stored. If you know the starting offset, you may pass it
390 * here. Otherwise, pass NULL, and one will be inferred from the items.
391 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
393 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
394 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
395 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
396 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
398 BOOL ret;
400 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
401 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
402 startingPointer);
404 if (pbEncoded[0] == ASN_SEQUENCE)
406 DWORD dataLen;
408 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
410 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
411 const BYTE *ptr = pbEncoded + 1 + lenBytes;
413 cbEncoded -= 1 + lenBytes;
414 if (cbEncoded < dataLen)
416 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
417 cbEncoded);
418 SetLastError(CRYPT_E_ASN1_CORRUPT);
419 ret = FALSE;
421 else
422 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
423 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
424 if (ret && cbDecoded != dataLen)
426 TRACE("expected %d decoded, got %d, failing\n", dataLen,
427 cbDecoded);
428 SetLastError(CRYPT_E_ASN1_CORRUPT);
429 ret = FALSE;
431 if (ret)
433 DWORD i, bytesNeeded = 0, structSize = 0;
435 for (i = 0; i < cItem; i++)
437 bytesNeeded += items[i].size;
438 structSize += items[i].minSize;
440 if (!pvStructInfo)
441 *pcbStructInfo = bytesNeeded;
442 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
443 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
445 BYTE *nextData;
447 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
448 pvStructInfo = *(BYTE **)pvStructInfo;
449 if (startingPointer)
450 nextData = (BYTE *)startingPointer;
451 else
452 nextData = (BYTE *)pvStructInfo + structSize;
453 memset(pvStructInfo, 0, structSize);
454 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
455 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
456 &cbDecoded);
461 else
463 SetLastError(CRYPT_E_ASN1_BADTAG);
464 ret = FALSE;
466 TRACE("returning %d (%08x)\n", ret, GetLastError());
467 return ret;
470 /* tag:
471 * The expected tag of the entire encoded array (usually a variant
472 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
473 * regardless of the tag seen.
474 * decodeFunc:
475 * used to decode each item in the array
476 * itemSize:
477 * is the minimum size of each decoded item
478 * hasPointer:
479 * indicates whether each item has a dynamic pointer
480 * pointerOffset:
481 * indicates the offset within itemSize at which the pointer exists
483 struct AsnArrayDescriptor
485 BYTE tag;
486 CryptDecodeObjectExFunc decodeFunc;
487 DWORD itemSize;
488 BOOL hasPointer;
489 DWORD pointerOffset;
492 struct AsnArrayItemSize
494 DWORD encodedLen;
495 DWORD size;
498 /* Decodes an array of like types into a struct GenericArray.
499 * The layout and decoding of the array are described by a struct
500 * AsnArrayDescriptor.
502 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
503 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
504 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
505 void *startingPointer)
507 BOOL ret = TRUE;
509 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
510 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
511 startingPointer);
513 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
515 DWORD dataLen;
517 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
519 DWORD bytesNeeded, cItems = 0;
520 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
521 /* There can be arbitrarily many items, but there is often only one.
523 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
525 bytesNeeded = sizeof(struct GenericArray);
526 if (dataLen)
528 const BYTE *ptr;
530 for (ptr = pbEncoded + 1 + lenBytes; ret &&
531 ptr - pbEncoded - 1 - lenBytes < dataLen; )
533 DWORD itemLenBytes, itemDataLen, size = 0;
535 itemLenBytes = GET_LEN_BYTES(ptr[1]);
536 /* Each item decoded may not tolerate extraneous bytes, so
537 * get the length of the next element and pass it directly.
539 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
540 &itemDataLen);
541 if (ret)
542 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
543 1 + itemLenBytes + itemDataLen,
544 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
545 &size);
546 if (ret)
548 DWORD nextLen;
550 cItems++;
551 if (itemSizes != &itemSize)
552 itemSizes = CryptMemRealloc(itemSizes,
553 cItems * sizeof(struct AsnArrayItemSize));
554 else
556 itemSizes =
557 CryptMemAlloc(
558 cItems * sizeof(struct AsnArrayItemSize));
559 if (itemSizes)
560 memcpy(itemSizes, &itemSize, sizeof(itemSize));
562 if (itemSizes)
564 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
565 + itemDataLen;
566 itemSizes[cItems - 1].size = size;
567 bytesNeeded += size;
568 ret = CRYPT_GetLen(ptr,
569 cbEncoded - (ptr - pbEncoded), &nextLen);
570 if (ret)
571 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
573 else
574 ret = FALSE;
578 if (ret)
580 if (!pvStructInfo)
581 *pcbStructInfo = bytesNeeded;
582 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
583 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
585 DWORD i;
586 BYTE *nextData;
587 const BYTE *ptr;
588 struct GenericArray *array;
590 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
591 pvStructInfo = *(BYTE **)pvStructInfo;
592 array = (struct GenericArray *)pvStructInfo;
593 array->cItems = cItems;
594 if (startingPointer)
595 array->rgItems = startingPointer;
596 else
597 array->rgItems = (BYTE *)array +
598 sizeof(struct GenericArray);
599 nextData = (BYTE *)array->rgItems +
600 array->cItems * arrayDesc->itemSize;
601 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
602 i < cItems && ptr - pbEncoded - 1 - lenBytes <
603 dataLen; i++)
605 if (arrayDesc->hasPointer)
606 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
607 + arrayDesc->pointerOffset) = nextData;
608 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
609 itemSizes[i].encodedLen,
610 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
611 array->rgItems + i * arrayDesc->itemSize,
612 &itemSizes[i].size);
613 if (ret)
615 DWORD nextLen;
617 nextData += itemSizes[i].size - arrayDesc->itemSize;
618 ret = CRYPT_GetLen(ptr,
619 cbEncoded - (ptr - pbEncoded), &nextLen);
620 if (ret)
621 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
626 if (itemSizes != &itemSize)
627 CryptMemFree(itemSizes);
630 else
632 SetLastError(CRYPT_E_ASN1_BADTAG);
633 ret = FALSE;
635 return ret;
638 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
639 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
640 * to CRYPT_E_ASN1_CORRUPT.
641 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
642 * set!
644 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
645 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
646 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
648 BOOL ret;
649 DWORD dataLen;
651 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
653 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
654 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
656 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
657 bytesNeeded += 1 + lenBytes + dataLen;
659 if (!pvStructInfo)
660 *pcbStructInfo = bytesNeeded;
661 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
662 pvStructInfo, pcbStructInfo, bytesNeeded)))
664 CRYPT_DER_BLOB *blob;
666 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
667 pvStructInfo = *(BYTE **)pvStructInfo;
668 blob = (CRYPT_DER_BLOB *)pvStructInfo;
669 blob->cbData = 1 + lenBytes + dataLen;
670 if (blob->cbData)
672 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
673 blob->pbData = (BYTE *)pbEncoded;
674 else
676 assert(blob->pbData);
677 memcpy(blob->pbData, pbEncoded, blob->cbData);
680 else
682 SetLastError(CRYPT_E_ASN1_CORRUPT);
683 ret = FALSE;
687 return ret;
690 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
691 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
692 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
693 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
695 BOOL ret;
697 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
698 pDecodePara, pvStructInfo, *pcbStructInfo);
700 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
701 * place.
703 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
704 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
705 pvStructInfo, pcbStructInfo);
706 if (ret && pvStructInfo)
708 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
710 if (blob->cbData)
712 DWORD i;
713 BYTE temp;
715 for (i = 0; i < blob->cbData / 2; i++)
717 temp = blob->pbData[i];
718 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
719 blob->pbData[blob->cbData - i - 1] = temp;
723 TRACE("returning %d (%08x)\n", ret, GetLastError());
724 return ret;
727 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
728 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
729 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
731 BOOL ret = TRUE;
733 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
734 pDecodePara, pvStructInfo, *pcbStructInfo);
736 __TRY
738 struct AsnDecodeSequenceItem items[] = {
739 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
740 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
741 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
742 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
743 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
744 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
745 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
746 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
747 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
748 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
751 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
752 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
753 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
754 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
755 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
757 __EXCEPT_PAGE_FAULT
759 SetLastError(STATUS_ACCESS_VIOLATION);
760 ret = FALSE;
762 __ENDTRY
764 TRACE("Returning %d (%08x)\n", ret, GetLastError());
765 return ret;
768 /* Internal function */
769 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
770 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
771 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
773 BOOL ret;
774 DWORD dataLen;
776 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
778 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
780 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
781 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
782 pvStructInfo, pcbStructInfo);
784 return ret;
787 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
788 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
789 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
791 BOOL ret;
793 struct AsnDecodeSequenceItem items[] = {
794 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
795 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
796 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
797 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
800 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
801 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
802 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
803 return ret;
806 /* Internal function */
807 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
808 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
809 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
811 BOOL ret;
812 DWORD dataLen;
814 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
816 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
818 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
819 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
820 pDecodePara, pvStructInfo, pcbStructInfo);
822 return ret;
825 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
826 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
827 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
829 BOOL ret = TRUE;
830 struct AsnDecodeSequenceItem items[] = {
831 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
832 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
833 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
834 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
835 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
836 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
837 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
838 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
839 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
840 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
841 Issuer.pbData) },
842 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
843 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
844 FALSE, 0 },
845 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
846 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
847 Subject.pbData) },
848 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
849 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
850 FALSE, TRUE, offsetof(CERT_INFO,
851 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
852 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
853 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
854 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
855 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
856 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
857 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
858 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
859 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
860 offsetof(CERT_INFO, rgExtension), 0 },
863 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
864 pDecodePara, pvStructInfo, *pcbStructInfo);
866 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
867 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
868 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
869 if (ret && pvStructInfo)
871 CERT_INFO *info;
873 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
874 info = *(CERT_INFO **)pvStructInfo;
875 else
876 info = (CERT_INFO *)pvStructInfo;
877 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
878 !info->Subject.cbData)
880 SetLastError(CRYPT_E_ASN1_CORRUPT);
881 /* Don't need to deallocate, because it should have failed on the
882 * first pass (and no memory was allocated.)
884 ret = FALSE;
888 TRACE("Returning %d (%08x)\n", ret, GetLastError());
889 return ret;
892 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
893 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
894 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
896 BOOL ret = TRUE;
898 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
899 pDecodePara, pvStructInfo, *pcbStructInfo);
901 __TRY
903 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
904 DWORD size = 0;
906 /* First try to decode it as a signed cert. */
907 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
908 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
909 (BYTE *)&signedCert, &size);
910 if (ret)
912 size = 0;
913 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
914 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
915 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
916 pcbStructInfo);
917 LocalFree(signedCert);
919 /* Failing that, try it as an unsigned cert */
920 if (!ret)
922 size = 0;
923 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
924 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
925 pDecodePara, pvStructInfo, pcbStructInfo);
928 __EXCEPT_PAGE_FAULT
930 SetLastError(STATUS_ACCESS_VIOLATION);
931 ret = FALSE;
933 __ENDTRY
935 TRACE("Returning %d (%08x)\n", ret, GetLastError());
936 return ret;
939 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
940 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
941 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
943 BOOL ret;
944 struct AsnDecodeSequenceItem items[] = {
945 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
946 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
947 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
948 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
949 sizeof(FILETIME), FALSE, FALSE, 0 },
950 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
951 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
952 offsetof(CRL_ENTRY, rgExtension), 0 },
954 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
956 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
957 *pcbStructInfo);
959 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
960 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
961 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
962 return ret;
965 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
966 * been set prior to calling.
968 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
969 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
970 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
972 BOOL ret;
973 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
974 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
975 offsetof(CRL_ENTRY, SerialNumber.pbData) };
976 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
978 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
979 pDecodePara, pvStructInfo, *pcbStructInfo);
981 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
982 pDecodePara, pvStructInfo, pcbStructInfo,
983 entries ? entries->rgItems : NULL);
984 TRACE("Returning %d (%08x)\n", ret, GetLastError());
985 return ret;
988 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
989 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
990 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
992 struct AsnDecodeSequenceItem items[] = {
993 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
994 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
995 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
996 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
997 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
998 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
999 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1000 Issuer.pbData) },
1001 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
1002 sizeof(FILETIME), FALSE, FALSE, 0 },
1003 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
1004 sizeof(FILETIME), TRUE, FALSE, 0 },
1005 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1006 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1007 offsetof(CRL_INFO, rgCRLEntry), 0 },
1008 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1009 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1010 offsetof(CRL_INFO, rgExtension), 0 },
1012 BOOL ret = TRUE;
1014 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1015 pDecodePara, pvStructInfo, *pcbStructInfo);
1017 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1018 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1019 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1021 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1022 return ret;
1025 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1026 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1027 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1029 BOOL ret = TRUE;
1031 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1032 pDecodePara, pvStructInfo, *pcbStructInfo);
1034 __TRY
1036 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1037 DWORD size = 0;
1039 /* First try to decode it as a signed crl. */
1040 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1041 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1042 (BYTE *)&signedCrl, &size);
1043 if (ret)
1045 size = 0;
1046 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1047 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1048 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1049 pvStructInfo, pcbStructInfo);
1050 LocalFree(signedCrl);
1052 /* Failing that, try it as an unsigned crl */
1053 if (!ret)
1055 size = 0;
1056 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1057 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1058 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1061 __EXCEPT_PAGE_FAULT
1063 SetLastError(STATUS_ACCESS_VIOLATION);
1064 ret = FALSE;
1066 __ENDTRY
1068 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1069 return ret;
1072 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType,
1073 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1074 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1076 BOOL ret = TRUE;
1077 DWORD dataLen;
1079 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1080 pDecodePara, pvStructInfo, *pcbStructInfo);
1082 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1084 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1085 DWORD bytesNeeded = sizeof(LPSTR);
1087 if (dataLen)
1089 /* The largest possible string for the first two components
1090 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1092 char firstTwo[6];
1093 const BYTE *ptr;
1095 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1096 pbEncoded[1 + lenBytes] / 40,
1097 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1098 * 40);
1099 bytesNeeded += strlen(firstTwo) + 1;
1100 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1101 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1103 /* large enough for ".4000000" */
1104 char str[9];
1105 int val = 0;
1107 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1108 (*ptr & 0x80))
1110 val <<= 7;
1111 val |= *ptr & 0x7f;
1112 ptr++;
1114 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1115 (*ptr & 0x80))
1117 SetLastError(CRYPT_E_ASN1_CORRUPT);
1118 ret = FALSE;
1120 else
1122 val <<= 7;
1123 val |= *ptr++;
1124 snprintf(str, sizeof(str), ".%d", val);
1125 bytesNeeded += strlen(str);
1129 if (!pvStructInfo)
1130 *pcbStructInfo = bytesNeeded;
1131 else if (*pcbStructInfo < bytesNeeded)
1133 *pcbStructInfo = bytesNeeded;
1134 SetLastError(ERROR_MORE_DATA);
1135 ret = FALSE;
1137 else
1139 if (dataLen)
1141 const BYTE *ptr;
1142 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1144 *pszObjId = 0;
1145 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1146 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1147 40) * 40);
1148 pszObjId += strlen(pszObjId);
1149 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1150 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1152 int val = 0;
1154 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1155 (*ptr & 0x80))
1157 val <<= 7;
1158 val |= *ptr & 0x7f;
1159 ptr++;
1161 val <<= 7;
1162 val |= *ptr++;
1163 sprintf(pszObjId, ".%d", val);
1164 pszObjId += strlen(pszObjId);
1167 else
1168 *(LPSTR *)pvStructInfo = NULL;
1169 *pcbStructInfo = bytesNeeded;
1172 return ret;
1175 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1176 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1177 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1179 BOOL ret;
1181 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1182 pDecodePara, pvStructInfo, *pcbStructInfo);
1184 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1185 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, lpszStructType,
1186 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
1187 pcbStructInfo);
1188 else
1190 SetLastError(CRYPT_E_ASN1_BADTAG);
1191 ret = FALSE;
1193 return ret;
1196 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1197 * ahead of time!
1199 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1200 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1201 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1203 struct AsnDecodeSequenceItem items[] = {
1204 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1205 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1206 offsetof(CERT_EXTENSION, pszObjId), 0 },
1207 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1208 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1209 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1210 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1211 offsetof(CERT_EXTENSION, Value.pbData) },
1213 BOOL ret = TRUE;
1214 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1216 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1217 *pcbStructInfo);
1219 if (ext)
1220 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1221 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1222 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1223 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1224 if (ext)
1225 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1226 debugstr_a(ext->pszObjId));
1227 TRACE("returning %d (%08x)\n", ret, GetLastError());
1228 return ret;
1231 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1232 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1233 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1235 BOOL ret = TRUE;
1236 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1237 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1238 offsetof(CERT_EXTENSION, pszObjId) };
1239 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1241 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1242 pDecodePara, pvStructInfo, *pcbStructInfo);
1244 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1245 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1246 return ret;
1249 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1250 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1251 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1253 BOOL ret = TRUE;
1255 __TRY
1257 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1258 lpszStructType, pbEncoded, cbEncoded,
1259 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1260 if (ret && pvStructInfo)
1262 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1263 pcbStructInfo, *pcbStructInfo);
1264 if (ret)
1266 CERT_EXTENSIONS *exts;
1268 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1269 pvStructInfo = *(BYTE **)pvStructInfo;
1270 exts = (CERT_EXTENSIONS *)pvStructInfo;
1271 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1272 sizeof(CERT_EXTENSIONS));
1273 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1274 lpszStructType, pbEncoded, cbEncoded,
1275 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1276 pcbStructInfo);
1280 __EXCEPT_PAGE_FAULT
1282 SetLastError(STATUS_ACCESS_VIOLATION);
1283 ret = FALSE;
1285 __ENDTRY
1286 return ret;
1289 /* Warning: this assumes the address of value->Value.pbData is already set, in
1290 * order to avoid overwriting memory. (In some cases, it may change it, if it
1291 * doesn't copy anything to memory.) Be sure to set it correctly!
1293 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1294 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1295 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1297 BOOL ret = TRUE;
1298 DWORD dataLen;
1299 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1301 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1303 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1304 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1306 switch (pbEncoded[0])
1308 case ASN_OCTETSTRING:
1309 valueType = CERT_RDN_OCTET_STRING;
1310 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1311 bytesNeeded += dataLen;
1312 break;
1313 case ASN_NUMERICSTRING:
1314 valueType = CERT_RDN_NUMERIC_STRING;
1315 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1316 bytesNeeded += dataLen;
1317 break;
1318 case ASN_PRINTABLESTRING:
1319 valueType = CERT_RDN_PRINTABLE_STRING;
1320 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1321 bytesNeeded += dataLen;
1322 break;
1323 case ASN_IA5STRING:
1324 valueType = CERT_RDN_IA5_STRING;
1325 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1326 bytesNeeded += dataLen;
1327 break;
1328 case ASN_T61STRING:
1329 valueType = CERT_RDN_T61_STRING;
1330 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1331 bytesNeeded += dataLen;
1332 break;
1333 case ASN_VIDEOTEXSTRING:
1334 valueType = CERT_RDN_VIDEOTEX_STRING;
1335 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1336 bytesNeeded += dataLen;
1337 break;
1338 case ASN_GRAPHICSTRING:
1339 valueType = CERT_RDN_GRAPHIC_STRING;
1340 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1341 bytesNeeded += dataLen;
1342 break;
1343 case ASN_VISIBLESTRING:
1344 valueType = CERT_RDN_VISIBLE_STRING;
1345 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1346 bytesNeeded += dataLen;
1347 break;
1348 case ASN_GENERALSTRING:
1349 valueType = CERT_RDN_GENERAL_STRING;
1350 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1351 bytesNeeded += dataLen;
1352 break;
1353 case ASN_UNIVERSALSTRING:
1354 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1355 SetLastError(CRYPT_E_ASN1_BADTAG);
1356 return FALSE;
1357 case ASN_BMPSTRING:
1358 valueType = CERT_RDN_BMP_STRING;
1359 bytesNeeded += dataLen;
1360 break;
1361 case ASN_UTF8STRING:
1362 valueType = CERT_RDN_UTF8_STRING;
1363 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1364 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1365 break;
1366 default:
1367 SetLastError(CRYPT_E_ASN1_BADTAG);
1368 return FALSE;
1371 if (!value)
1372 *pcbStructInfo = bytesNeeded;
1373 else if (*pcbStructInfo < bytesNeeded)
1375 *pcbStructInfo = bytesNeeded;
1376 SetLastError(ERROR_MORE_DATA);
1377 ret = FALSE;
1379 else
1381 *pcbStructInfo = bytesNeeded;
1382 value->dwValueType = valueType;
1383 if (dataLen)
1385 DWORD i;
1387 assert(value->Value.pbData);
1388 switch (pbEncoded[0])
1390 case ASN_OCTETSTRING:
1391 case ASN_NUMERICSTRING:
1392 case ASN_PRINTABLESTRING:
1393 case ASN_IA5STRING:
1394 case ASN_T61STRING:
1395 case ASN_VIDEOTEXSTRING:
1396 case ASN_GRAPHICSTRING:
1397 case ASN_VISIBLESTRING:
1398 case ASN_GENERALSTRING:
1399 value->Value.cbData = dataLen;
1400 if (dataLen)
1402 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1403 memcpy(value->Value.pbData,
1404 pbEncoded + 1 + lenBytes, dataLen);
1405 else
1406 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1407 lenBytes;
1409 break;
1410 case ASN_BMPSTRING:
1412 LPWSTR str = (LPWSTR)value->Value.pbData;
1414 value->Value.cbData = dataLen;
1415 for (i = 0; i < dataLen / 2; i++)
1416 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1417 pbEncoded[1 + lenBytes + 2 * i + 1];
1418 break;
1420 case ASN_UTF8STRING:
1422 LPWSTR str = (LPWSTR)value->Value.pbData;
1424 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1425 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1426 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1427 break;
1431 else
1433 value->Value.cbData = 0;
1434 value->Value.pbData = NULL;
1438 return ret;
1441 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1442 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1443 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1445 BOOL ret = TRUE;
1447 __TRY
1449 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1450 lpszStructType, pbEncoded, cbEncoded,
1451 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1452 if (ret && pvStructInfo)
1454 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1455 pcbStructInfo, *pcbStructInfo);
1456 if (ret)
1458 CERT_NAME_VALUE *value;
1460 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1461 pvStructInfo = *(BYTE **)pvStructInfo;
1462 value = (CERT_NAME_VALUE *)pvStructInfo;
1463 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1464 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1465 lpszStructType, pbEncoded, cbEncoded,
1466 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1467 pcbStructInfo);
1471 __EXCEPT_PAGE_FAULT
1473 SetLastError(STATUS_ACCESS_VIOLATION);
1474 ret = FALSE;
1476 __ENDTRY
1477 return ret;
1480 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1481 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1482 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1483 void *pvStructInfo, DWORD *pcbStructInfo)
1485 BOOL ret = TRUE;
1486 DWORD dataLen;
1487 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1489 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1491 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1492 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1494 switch (pbEncoded[0])
1496 case ASN_NUMERICSTRING:
1497 valueType = CERT_RDN_NUMERIC_STRING;
1498 bytesNeeded += dataLen * 2;
1499 break;
1500 case ASN_PRINTABLESTRING:
1501 valueType = CERT_RDN_PRINTABLE_STRING;
1502 bytesNeeded += dataLen * 2;
1503 break;
1504 case ASN_IA5STRING:
1505 valueType = CERT_RDN_IA5_STRING;
1506 bytesNeeded += dataLen * 2;
1507 break;
1508 case ASN_T61STRING:
1509 valueType = CERT_RDN_T61_STRING;
1510 bytesNeeded += dataLen * 2;
1511 break;
1512 case ASN_VIDEOTEXSTRING:
1513 valueType = CERT_RDN_VIDEOTEX_STRING;
1514 bytesNeeded += dataLen * 2;
1515 break;
1516 case ASN_GRAPHICSTRING:
1517 valueType = CERT_RDN_GRAPHIC_STRING;
1518 bytesNeeded += dataLen * 2;
1519 break;
1520 case ASN_VISIBLESTRING:
1521 valueType = CERT_RDN_VISIBLE_STRING;
1522 bytesNeeded += dataLen * 2;
1523 break;
1524 case ASN_GENERALSTRING:
1525 valueType = CERT_RDN_GENERAL_STRING;
1526 bytesNeeded += dataLen * 2;
1527 break;
1528 case ASN_UNIVERSALSTRING:
1529 valueType = CERT_RDN_UNIVERSAL_STRING;
1530 bytesNeeded += dataLen / 2;
1531 break;
1532 case ASN_BMPSTRING:
1533 valueType = CERT_RDN_BMP_STRING;
1534 bytesNeeded += dataLen;
1535 break;
1536 case ASN_UTF8STRING:
1537 valueType = CERT_RDN_UTF8_STRING;
1538 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1539 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1540 break;
1541 default:
1542 SetLastError(CRYPT_E_ASN1_BADTAG);
1543 return FALSE;
1546 if (!value)
1547 *pcbStructInfo = bytesNeeded;
1548 else if (*pcbStructInfo < bytesNeeded)
1550 *pcbStructInfo = bytesNeeded;
1551 SetLastError(ERROR_MORE_DATA);
1552 ret = FALSE;
1554 else
1556 *pcbStructInfo = bytesNeeded;
1557 value->dwValueType = valueType;
1558 if (dataLen)
1560 DWORD i;
1561 LPWSTR str = (LPWSTR)value->Value.pbData;
1563 assert(value->Value.pbData);
1564 switch (pbEncoded[0])
1566 case ASN_NUMERICSTRING:
1567 case ASN_PRINTABLESTRING:
1568 case ASN_IA5STRING:
1569 case ASN_T61STRING:
1570 case ASN_VIDEOTEXSTRING:
1571 case ASN_GRAPHICSTRING:
1572 case ASN_VISIBLESTRING:
1573 case ASN_GENERALSTRING:
1574 value->Value.cbData = dataLen * 2;
1575 for (i = 0; i < dataLen; i++)
1576 str[i] = pbEncoded[1 + lenBytes + i];
1577 break;
1578 case ASN_UNIVERSALSTRING:
1579 value->Value.cbData = dataLen / 2;
1580 for (i = 0; i < dataLen / 4; i++)
1581 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1582 | pbEncoded[1 + lenBytes + 2 * i + 3];
1583 break;
1584 case ASN_BMPSTRING:
1585 value->Value.cbData = dataLen;
1586 for (i = 0; i < dataLen / 2; i++)
1587 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1588 pbEncoded[1 + lenBytes + 2 * i + 1];
1589 break;
1590 case ASN_UTF8STRING:
1591 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1592 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1593 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1594 break;
1597 else
1599 value->Value.cbData = 0;
1600 value->Value.pbData = NULL;
1604 return ret;
1607 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1608 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1609 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1611 BOOL ret = TRUE;
1613 __TRY
1615 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1616 lpszStructType, pbEncoded, cbEncoded,
1617 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1618 if (ret && pvStructInfo)
1620 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1621 pcbStructInfo, *pcbStructInfo);
1622 if (ret)
1624 CERT_NAME_VALUE *value;
1626 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1627 pvStructInfo = *(BYTE **)pvStructInfo;
1628 value = (CERT_NAME_VALUE *)pvStructInfo;
1629 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1630 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1631 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1632 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1633 pcbStructInfo);
1637 __EXCEPT_PAGE_FAULT
1639 SetLastError(STATUS_ACCESS_VIOLATION);
1640 ret = FALSE;
1642 __ENDTRY
1643 return ret;
1646 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1647 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1648 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1650 BOOL ret;
1651 struct AsnDecodeSequenceItem items[] = {
1652 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1653 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1654 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1655 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1656 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1657 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1659 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1661 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1662 pvStructInfo, *pcbStructInfo);
1664 if (attr)
1665 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1666 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1667 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1668 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1669 if (attr)
1671 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1672 debugstr_a(attr->pszObjId));
1673 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1675 TRACE("returning %d (%08x)\n", ret, GetLastError());
1676 return ret;
1679 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1680 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1681 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1683 BOOL ret = TRUE;
1684 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1685 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1686 offsetof(CERT_RDN_ATTR, pszObjId) };
1687 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1689 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1690 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1691 return ret;
1694 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1695 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1696 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1698 BOOL ret = TRUE;
1700 __TRY
1702 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1703 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1704 offsetof(CERT_RDN, rgRDNAttr) };
1706 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1707 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1709 __EXCEPT_PAGE_FAULT
1711 SetLastError(STATUS_ACCESS_VIOLATION);
1712 ret = FALSE;
1714 __ENDTRY
1715 return ret;
1718 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
1719 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1720 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1722 BOOL ret;
1723 struct AsnDecodeSequenceItem items[] = {
1724 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1725 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1726 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1727 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1728 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1729 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1731 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1733 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1734 pvStructInfo, *pcbStructInfo);
1736 if (attr)
1737 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1738 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1739 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1740 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1741 if (attr)
1743 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1744 debugstr_a(attr->pszObjId));
1745 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1747 TRACE("returning %d (%08x)\n", ret, GetLastError());
1748 return ret;
1751 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
1752 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1753 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1755 BOOL ret = TRUE;
1756 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1757 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1758 offsetof(CERT_RDN_ATTR, pszObjId) };
1759 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1761 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1762 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1763 return ret;
1766 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1767 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1768 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1770 BOOL ret = TRUE;
1772 __TRY
1774 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1775 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1776 offsetof(CERT_RDN, rgRDNAttr) };
1778 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1779 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1781 __EXCEPT_PAGE_FAULT
1783 SetLastError(STATUS_ACCESS_VIOLATION);
1784 ret = FALSE;
1786 __ENDTRY
1787 return ret;
1790 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1791 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1792 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1794 BOOL ret = TRUE;
1795 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1797 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1798 pDecodePara, pvStructInfo, *pcbStructInfo);
1800 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1801 bytesNeeded += cbEncoded;
1802 if (!pvStructInfo)
1803 *pcbStructInfo = bytesNeeded;
1804 else if (*pcbStructInfo < bytesNeeded)
1806 SetLastError(ERROR_MORE_DATA);
1807 *pcbStructInfo = bytesNeeded;
1808 ret = FALSE;
1810 else
1812 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1814 *pcbStructInfo = bytesNeeded;
1815 blob->cbData = cbEncoded;
1816 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1817 blob->pbData = (LPBYTE)pbEncoded;
1818 else
1820 assert(blob->pbData);
1821 memcpy(blob->pbData, pbEncoded, blob->cbData);
1824 return ret;
1827 static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType,
1828 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1829 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1831 BOOL ret;
1832 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
1833 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1834 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1836 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1837 pDecodePara, pvStructInfo, *pcbStructInfo);
1839 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1840 pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
1841 return ret;
1844 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1845 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1846 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1848 BOOL ret = FALSE;
1850 __TRY
1852 struct AsnDecodeSequenceItem items[] = {
1853 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1854 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1855 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1856 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1857 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1858 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1860 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1862 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1863 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1864 pDecodePara, pvStructInfo, pcbStructInfo, attr ? attr->pszObjId :
1865 NULL);
1867 __EXCEPT_PAGE_FAULT
1869 SetLastError(STATUS_ACCESS_VIOLATION);
1871 __ENDTRY
1872 TRACE("returning %d\n", ret);
1873 return ret;
1876 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal(
1877 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1878 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1879 void *pvStructInfo, DWORD *pcbStructInfo)
1881 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodePKCSAttribute,
1882 sizeof(CRYPT_ATTRIBUTE), TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
1883 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1884 BOOL ret;
1886 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1887 pDecodePara, pvStructInfo, pcbStructInfo, attrs ? attrs->rgAttr :
1888 NULL);
1889 return ret;
1892 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
1893 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1894 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1896 BOOL ret = FALSE;
1898 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1899 pDecodePara, pvStructInfo, *pcbStructInfo);
1901 __TRY
1903 DWORD bytesNeeded;
1905 if (!cbEncoded)
1906 SetLastError(CRYPT_E_ASN1_EOD);
1907 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
1908 SetLastError(CRYPT_E_ASN1_CORRUPT);
1909 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(
1910 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1911 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1913 if (!pvStructInfo)
1914 *pcbStructInfo = bytesNeeded;
1915 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1916 pvStructInfo, pcbStructInfo, bytesNeeded)))
1918 PCRYPT_ATTRIBUTES attrs;
1920 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1921 pvStructInfo = *(BYTE **)pvStructInfo;
1922 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1923 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
1924 sizeof(CRYPT_ATTRIBUTES));
1925 ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1926 lpszStructType, pbEncoded, cbEncoded,
1927 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1928 &bytesNeeded);
1932 __EXCEPT_PAGE_FAULT
1934 SetLastError(STATUS_ACCESS_VIOLATION);
1936 __ENDTRY
1937 TRACE("returning %d\n", ret);
1938 return ret;
1941 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1942 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1943 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1945 CRYPT_ALGORITHM_IDENTIFIER *algo =
1946 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1947 BOOL ret = TRUE;
1948 struct AsnDecodeSequenceItem items[] = {
1949 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1950 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1951 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1952 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1953 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1954 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1957 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1958 pDecodePara, pvStructInfo, *pcbStructInfo);
1960 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1961 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1962 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1963 if (ret && pvStructInfo)
1965 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1966 debugstr_a(algo->pszObjId));
1968 return ret;
1971 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1972 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1973 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1975 BOOL ret = TRUE;
1976 struct AsnDecodeSequenceItem items[] = {
1977 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1978 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1979 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1980 Algorithm.pszObjId) },
1981 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1982 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1983 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1985 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1987 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1988 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1989 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1990 info->Algorithm.Parameters.pbData : NULL);
1991 return ret;
1994 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1995 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1996 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1998 BOOL ret = TRUE;
2000 __TRY
2002 DWORD bytesNeeded;
2004 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2005 lpszStructType, pbEncoded, cbEncoded,
2006 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2008 if (!pvStructInfo)
2009 *pcbStructInfo = bytesNeeded;
2010 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2011 pvStructInfo, pcbStructInfo, bytesNeeded)))
2013 PCERT_PUBLIC_KEY_INFO info;
2015 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2016 pvStructInfo = *(BYTE **)pvStructInfo;
2017 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2018 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2019 sizeof(CERT_PUBLIC_KEY_INFO);
2020 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2021 lpszStructType, pbEncoded, cbEncoded,
2022 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2023 &bytesNeeded);
2027 __EXCEPT_PAGE_FAULT
2029 SetLastError(STATUS_ACCESS_VIOLATION);
2030 ret = FALSE;
2032 __ENDTRY
2033 return ret;
2036 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2037 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2038 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2040 BOOL ret;
2042 if (cbEncoded < 3)
2044 SetLastError(CRYPT_E_ASN1_CORRUPT);
2045 return FALSE;
2047 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2049 SetLastError(CRYPT_E_ASN1_CORRUPT);
2050 return FALSE;
2052 if (pbEncoded[1] > 1)
2054 SetLastError(CRYPT_E_ASN1_CORRUPT);
2055 return FALSE;
2057 if (!pvStructInfo)
2059 *pcbStructInfo = sizeof(BOOL);
2060 ret = TRUE;
2062 else if (*pcbStructInfo < sizeof(BOOL))
2064 *pcbStructInfo = sizeof(BOOL);
2065 SetLastError(ERROR_MORE_DATA);
2066 ret = FALSE;
2068 else
2070 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2071 ret = TRUE;
2073 TRACE("returning %d (%08x)\n", ret, GetLastError());
2074 return ret;
2077 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
2078 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2079 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2081 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2082 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2083 BOOL ret;
2085 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2086 pDecodePara, pvStructInfo, *pcbStructInfo);
2088 if (cbEncoded < 2)
2090 SetLastError(CRYPT_E_ASN1_CORRUPT);
2091 return FALSE;
2093 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2094 if (1 + lenBytes > cbEncoded)
2096 SetLastError(CRYPT_E_ASN1_CORRUPT);
2097 return FALSE;
2099 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2101 switch (pbEncoded[0] & ASN_TYPE_MASK)
2103 case 1: /* rfc822Name */
2104 case 2: /* dNSName */
2105 case 6: /* uniformResourceIdentifier */
2106 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2107 break;
2108 case 4: /* directoryName */
2109 case 7: /* iPAddress */
2110 bytesNeeded += dataLen;
2111 break;
2112 case 8: /* registeredID */
2113 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, NULL,
2114 pbEncoded, cbEncoded, 0, NULL, NULL, &dataLen);
2115 if (ret)
2117 /* FIXME: ugly, shouldn't need to know internals of OID decode
2118 * function to use it.
2120 bytesNeeded += dataLen - sizeof(LPSTR);
2122 break;
2123 case 0: /* otherName */
2124 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2125 SetLastError(CRYPT_E_ASN1_BADTAG);
2126 ret = FALSE;
2127 break;
2128 case 3: /* x400Address, unimplemented */
2129 case 5: /* ediPartyName, unimplemented */
2130 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2131 SetLastError(CRYPT_E_ASN1_BADTAG);
2132 ret = FALSE;
2133 break;
2134 default:
2135 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2136 SetLastError(CRYPT_E_ASN1_CORRUPT);
2137 ret = FALSE;
2139 if (ret)
2141 if (!entry)
2142 *pcbStructInfo = bytesNeeded;
2143 else if (*pcbStructInfo < bytesNeeded)
2145 *pcbStructInfo = bytesNeeded;
2146 SetLastError(ERROR_MORE_DATA);
2147 ret = FALSE;
2149 else
2151 *pcbStructInfo = bytesNeeded;
2152 /* MS used values one greater than the asn1 ones.. sigh */
2153 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2154 switch (pbEncoded[0] & ASN_TYPE_MASK)
2156 case 1: /* rfc822Name */
2157 case 2: /* dNSName */
2158 case 6: /* uniformResourceIdentifier */
2160 DWORD i;
2162 for (i = 0; i < dataLen; i++)
2163 entry->u.pwszURL[i] =
2164 (WCHAR)pbEncoded[1 + lenBytes + i];
2165 entry->u.pwszURL[i] = 0;
2166 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2167 debugstr_w(entry->u.pwszURL));
2168 break;
2170 case 4: /* directoryName */
2171 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2172 /* The data are memory-equivalent with the IPAddress case,
2173 * fall-through
2175 case 7: /* iPAddress */
2176 /* The next data pointer is in the pwszURL spot, that is,
2177 * the first 4 bytes. Need to move it to the next spot.
2179 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2180 entry->u.IPAddress.cbData = dataLen;
2181 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2182 dataLen);
2183 break;
2184 case 8: /* registeredID */
2185 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, NULL,
2186 pbEncoded, cbEncoded, 0, NULL, &entry->u.pszRegisteredID,
2187 &dataLen);
2188 break;
2193 return ret;
2196 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2197 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2198 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2200 BOOL ret = TRUE;
2201 struct AsnArrayDescriptor arrayDesc = { 0,
2202 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2203 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2204 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2206 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2207 pDecodePara, pvStructInfo, *pcbStructInfo);
2209 if (info)
2210 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2211 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2212 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2213 return ret;
2216 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2217 static BOOL WINAPI CRYPT_AsnDecodeIntegerSwapBytes(DWORD dwCertEncodingType,
2218 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2219 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2221 BOOL ret;
2223 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2224 pDecodePara, pvStructInfo, *pcbStructInfo);
2226 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2227 * place.
2229 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType, lpszStructType,
2230 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
2231 pvStructInfo, pcbStructInfo);
2232 if (ret && pvStructInfo)
2234 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2236 if (blob->cbData)
2238 DWORD i;
2239 BYTE temp;
2241 for (i = 0; i < blob->cbData / 2; i++)
2243 temp = blob->pbData[i];
2244 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2245 blob->pbData[blob->cbData - i - 1] = temp;
2249 TRACE("returning %d (%08x)\n", ret, GetLastError());
2250 return ret;
2253 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2254 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2255 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2257 BOOL ret;
2259 __TRY
2261 struct AsnDecodeSequenceItem items[] = {
2262 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2263 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2264 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2265 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2266 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2267 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2268 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2269 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2270 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2271 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2272 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2275 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2276 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2277 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2279 __EXCEPT_PAGE_FAULT
2281 SetLastError(STATUS_ACCESS_VIOLATION);
2282 ret = FALSE;
2284 __ENDTRY
2285 return ret;
2288 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2289 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2290 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2292 BOOL ret;
2294 __TRY
2296 struct AsnDecodeSequenceItem items[] = {
2297 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2298 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2299 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2300 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2301 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2302 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2303 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2304 AuthorityCertIssuer.rgAltEntry), 0 },
2305 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2306 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2307 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2308 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2309 AuthorityCertSerialNumber.pbData), 0 },
2312 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2313 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2314 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2316 __EXCEPT_PAGE_FAULT
2318 SetLastError(STATUS_ACCESS_VIOLATION);
2319 ret = FALSE;
2321 __ENDTRY
2322 return ret;
2325 static BOOL WINAPI CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType,
2326 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2327 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2329 BOOL ret;
2330 DWORD dataLen;
2332 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2333 pDecodePara, pvStructInfo, *pcbStructInfo);
2335 /* The caller has already checked the tag, no need to check it again.
2336 * Check the outer length is valid by calling CRYPT_GetLen:
2338 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2340 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2341 DWORD innerLen;
2343 pbEncoded += 1 + lenBytes;
2344 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2345 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2347 ret = CRYPT_AsnDecodeCopyBytes(dwCertEncodingType, NULL,
2348 pbEncoded, dataLen, dwFlags, pDecodePara, pvStructInfo,
2349 pcbStructInfo);
2352 return ret;
2355 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfoInternal(
2356 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2357 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2358 void *pvStructInfo, DWORD *pcbStructInfo)
2360 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2361 struct AsnDecodeSequenceItem items[] = {
2362 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2363 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2364 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2365 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2366 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2367 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2368 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2370 BOOL ret;
2372 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2373 pDecodePara, pvStructInfo, *pcbStructInfo);
2375 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2376 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2377 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->pszObjId : NULL);
2378 return ret;
2381 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2382 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2383 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2385 BOOL ret = FALSE;
2387 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2388 pDecodePara, pvStructInfo, *pcbStructInfo);
2390 __TRY
2392 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2393 lpszStructType, pbEncoded, cbEncoded,
2394 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
2395 if (ret && pvStructInfo)
2397 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2398 pcbStructInfo, *pcbStructInfo);
2399 if (ret)
2401 CRYPT_CONTENT_INFO *info;
2403 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2404 pvStructInfo = *(BYTE **)pvStructInfo;
2405 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2406 info->pszObjId = (LPSTR)((BYTE *)info +
2407 sizeof(CRYPT_CONTENT_INFO));
2408 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2409 lpszStructType, pbEncoded, cbEncoded,
2410 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2411 pcbStructInfo);
2415 __EXCEPT_PAGE_FAULT
2417 SetLastError(STATUS_ACCESS_VIOLATION);
2419 __ENDTRY
2420 return ret;
2423 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2424 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2425 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2427 BOOL ret;
2428 struct AsnDecodeSequenceItem items[] = {
2429 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version), CRYPT_AsnDecodeInt,
2430 sizeof(DWORD), FALSE, FALSE, 0, 0 },
2431 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2432 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2433 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2434 0 },
2435 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2436 CRYPT_AsnDecodePKCSContentInfoInternal,
2437 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2438 ContentInfo.pszObjId), 0 },
2439 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2440 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2441 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2444 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
2445 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2446 pDecodePara, digestedData, pcbDigestedData, NULL);
2447 return ret;
2450 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2451 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2452 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2454 BOOL ret = TRUE;
2456 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2457 pDecodePara, pvStructInfo, *pcbStructInfo);
2459 __TRY
2461 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2462 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2463 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2465 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2466 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2468 __EXCEPT_PAGE_FAULT
2470 SetLastError(STATUS_ACCESS_VIOLATION);
2471 ret = FALSE;
2473 __ENDTRY
2474 return ret;
2477 struct PATH_LEN_CONSTRAINT
2479 BOOL fPathLenConstraint;
2480 DWORD dwPathLenConstraint;
2483 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2484 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2485 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2487 BOOL ret = TRUE;
2489 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2490 pvStructInfo, *pcbStructInfo);
2492 if (cbEncoded)
2494 if (pbEncoded[0] == ASN_INTEGER)
2496 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2498 if (!pvStructInfo)
2499 *pcbStructInfo = bytesNeeded;
2500 else if (*pcbStructInfo < bytesNeeded)
2502 SetLastError(ERROR_MORE_DATA);
2503 *pcbStructInfo = bytesNeeded;
2504 ret = FALSE;
2506 else
2508 struct PATH_LEN_CONSTRAINT *constraint =
2509 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2510 DWORD size = sizeof(constraint->dwPathLenConstraint);
2512 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2513 pbEncoded, cbEncoded, 0, NULL,
2514 &constraint->dwPathLenConstraint, &size);
2515 if (ret)
2516 constraint->fPathLenConstraint = TRUE;
2517 TRACE("got an int, dwPathLenConstraint is %d\n",
2518 constraint->dwPathLenConstraint);
2521 else
2523 SetLastError(CRYPT_E_ASN1_CORRUPT);
2524 ret = FALSE;
2527 TRACE("returning %d (%08x)\n", ret, GetLastError());
2528 return ret;
2531 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2532 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2533 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2535 BOOL ret;
2536 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2537 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2538 offsetof(CERT_NAME_BLOB, pbData) };
2539 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2541 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2542 pDecodePara, pvStructInfo, *pcbStructInfo);
2544 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2545 pDecodePara, pvStructInfo, pcbStructInfo,
2546 entries ? entries->rgItems : NULL);
2547 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2548 return ret;
2551 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2552 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2553 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2555 BOOL ret;
2557 __TRY
2559 struct AsnDecodeSequenceItem items[] = {
2560 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2561 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2562 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2563 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2564 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2565 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2566 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2567 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2568 sizeof(struct GenericArray), TRUE, TRUE,
2569 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2572 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2573 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2574 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2576 __EXCEPT_PAGE_FAULT
2578 SetLastError(STATUS_ACCESS_VIOLATION);
2579 ret = FALSE;
2581 __ENDTRY
2582 return ret;
2585 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2586 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2587 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2589 BOOL ret;
2591 __TRY
2593 struct AsnDecodeSequenceItem items[] = {
2594 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2595 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2596 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2597 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2598 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2601 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2602 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2603 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2605 __EXCEPT_PAGE_FAULT
2607 SetLastError(STATUS_ACCESS_VIOLATION);
2608 ret = FALSE;
2610 __ENDTRY
2611 return ret;
2614 #define RSA1_MAGIC 0x31415352
2616 struct DECODED_RSA_PUB_KEY
2618 DWORD pubexp;
2619 CRYPT_INTEGER_BLOB modulus;
2622 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2623 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2624 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2626 BOOL ret;
2628 __TRY
2630 struct AsnDecodeSequenceItem items[] = {
2631 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2632 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2633 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2634 0 },
2635 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2636 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2638 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2639 DWORD size = 0;
2641 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2642 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2643 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2644 if (ret)
2646 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2647 decodedKey->modulus.cbData;
2649 if (!pvStructInfo)
2651 *pcbStructInfo = bytesNeeded;
2652 ret = TRUE;
2654 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2655 pvStructInfo, pcbStructInfo, bytesNeeded)))
2657 BLOBHEADER *hdr;
2658 RSAPUBKEY *rsaPubKey;
2660 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2661 pvStructInfo = *(BYTE **)pvStructInfo;
2662 hdr = (BLOBHEADER *)pvStructInfo;
2663 hdr->bType = PUBLICKEYBLOB;
2664 hdr->bVersion = CUR_BLOB_VERSION;
2665 hdr->reserved = 0;
2666 hdr->aiKeyAlg = CALG_RSA_KEYX;
2667 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2668 sizeof(BLOBHEADER));
2669 rsaPubKey->magic = RSA1_MAGIC;
2670 rsaPubKey->pubexp = decodedKey->pubexp;
2671 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2672 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2673 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2674 decodedKey->modulus.cbData);
2676 LocalFree(decodedKey);
2679 __EXCEPT_PAGE_FAULT
2681 SetLastError(STATUS_ACCESS_VIOLATION);
2682 ret = FALSE;
2684 __ENDTRY
2685 return ret;
2688 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2689 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2690 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2692 BOOL ret;
2693 DWORD bytesNeeded, dataLen;
2695 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2696 pDecodePara, pvStructInfo, *pcbStructInfo);
2698 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2700 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2701 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2702 else
2703 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2704 if (!pvStructInfo)
2705 *pcbStructInfo = bytesNeeded;
2706 else if (*pcbStructInfo < bytesNeeded)
2708 SetLastError(ERROR_MORE_DATA);
2709 *pcbStructInfo = bytesNeeded;
2710 ret = FALSE;
2712 else
2714 CRYPT_DATA_BLOB *blob;
2715 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2717 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2718 blob->cbData = dataLen;
2719 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2720 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2721 else
2723 assert(blob->pbData);
2724 if (blob->cbData)
2725 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2726 blob->cbData);
2730 return ret;
2733 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2734 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2735 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2737 BOOL ret;
2739 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2740 pDecodePara, pvStructInfo, *pcbStructInfo);
2742 __TRY
2744 DWORD bytesNeeded;
2746 if (!cbEncoded)
2748 SetLastError(CRYPT_E_ASN1_CORRUPT);
2749 ret = FALSE;
2751 else if (pbEncoded[0] != ASN_OCTETSTRING)
2753 SetLastError(CRYPT_E_ASN1_BADTAG);
2754 ret = FALSE;
2756 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2757 lpszStructType, pbEncoded, cbEncoded,
2758 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2760 if (!pvStructInfo)
2761 *pcbStructInfo = bytesNeeded;
2762 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2763 pvStructInfo, pcbStructInfo, bytesNeeded)))
2765 CRYPT_DATA_BLOB *blob;
2767 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2768 pvStructInfo = *(BYTE **)pvStructInfo;
2769 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2770 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2771 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2772 lpszStructType, pbEncoded, cbEncoded,
2773 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2774 &bytesNeeded);
2778 __EXCEPT_PAGE_FAULT
2780 SetLastError(STATUS_ACCESS_VIOLATION);
2781 ret = FALSE;
2783 __ENDTRY
2784 return ret;
2787 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2788 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2789 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2791 BOOL ret;
2793 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2794 pDecodePara, pvStructInfo, *pcbStructInfo);
2796 if (pbEncoded[0] == ASN_BITSTRING)
2798 DWORD bytesNeeded, dataLen;
2800 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2802 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2803 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2804 else
2805 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2806 if (!pvStructInfo)
2807 *pcbStructInfo = bytesNeeded;
2808 else if (*pcbStructInfo < bytesNeeded)
2810 *pcbStructInfo = bytesNeeded;
2811 SetLastError(ERROR_MORE_DATA);
2812 ret = FALSE;
2814 else
2816 CRYPT_BIT_BLOB *blob;
2818 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2819 blob->cbData = dataLen - 1;
2820 blob->cUnusedBits = *(pbEncoded + 1 +
2821 GET_LEN_BYTES(pbEncoded[1]));
2822 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2824 blob->pbData = (BYTE *)pbEncoded + 2 +
2825 GET_LEN_BYTES(pbEncoded[1]);
2827 else
2829 assert(blob->pbData);
2830 if (blob->cbData)
2832 BYTE mask = 0xff << blob->cUnusedBits;
2834 memcpy(blob->pbData, pbEncoded + 2 +
2835 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2836 blob->pbData[blob->cbData - 1] &= mask;
2842 else
2844 SetLastError(CRYPT_E_ASN1_BADTAG);
2845 ret = FALSE;
2847 TRACE("returning %d (%08x)\n", ret, GetLastError());
2848 return ret;
2851 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2852 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2853 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2855 BOOL ret;
2857 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2858 pDecodePara, pvStructInfo, pcbStructInfo);
2860 __TRY
2862 DWORD bytesNeeded;
2864 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2865 lpszStructType, pbEncoded, cbEncoded,
2866 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2868 if (!pvStructInfo)
2869 *pcbStructInfo = bytesNeeded;
2870 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2871 pvStructInfo, pcbStructInfo, bytesNeeded)))
2873 CRYPT_BIT_BLOB *blob;
2875 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2876 pvStructInfo = *(BYTE **)pvStructInfo;
2877 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2878 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2879 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2880 lpszStructType, pbEncoded, cbEncoded,
2881 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2882 &bytesNeeded);
2886 __EXCEPT_PAGE_FAULT
2888 SetLastError(STATUS_ACCESS_VIOLATION);
2889 ret = FALSE;
2891 __ENDTRY
2892 TRACE("returning %d (%08x)\n", ret, GetLastError());
2893 return ret;
2896 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2897 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2898 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2900 BOOL ret;
2902 if (!pvStructInfo)
2904 *pcbStructInfo = sizeof(int);
2905 return TRUE;
2907 __TRY
2909 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2910 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2911 DWORD size = sizeof(buf);
2913 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2914 if (pbEncoded[0] != ASN_INTEGER)
2916 SetLastError(CRYPT_E_ASN1_BADTAG);
2917 ret = FALSE;
2919 else
2920 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2921 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
2922 &size);
2923 if (ret)
2925 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2926 pvStructInfo, pcbStructInfo, sizeof(int))))
2928 int val, i;
2930 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2931 pvStructInfo = *(BYTE **)pvStructInfo;
2932 if (blob->pbData[blob->cbData - 1] & 0x80)
2934 /* initialize to a negative value to sign-extend */
2935 val = -1;
2937 else
2938 val = 0;
2939 for (i = 0; i < blob->cbData; i++)
2941 val <<= 8;
2942 val |= blob->pbData[blob->cbData - i - 1];
2944 memcpy(pvStructInfo, &val, sizeof(int));
2947 else if (GetLastError() == ERROR_MORE_DATA)
2948 SetLastError(CRYPT_E_ASN1_LARGE);
2950 __EXCEPT_PAGE_FAULT
2952 SetLastError(STATUS_ACCESS_VIOLATION);
2953 ret = FALSE;
2955 __ENDTRY
2956 return ret;
2959 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2960 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2961 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2963 BOOL ret;
2964 DWORD bytesNeeded, dataLen;
2966 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2968 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2970 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2971 if (!pvStructInfo)
2972 *pcbStructInfo = bytesNeeded;
2973 else if (*pcbStructInfo < bytesNeeded)
2975 *pcbStructInfo = bytesNeeded;
2976 SetLastError(ERROR_MORE_DATA);
2977 ret = FALSE;
2979 else
2981 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2983 blob->cbData = dataLen;
2984 assert(blob->pbData);
2985 if (blob->cbData)
2987 DWORD i;
2989 for (i = 0; i < blob->cbData; i++)
2991 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2992 dataLen - i - 1);
2997 return ret;
3000 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3001 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3002 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3004 BOOL ret;
3006 __TRY
3008 DWORD bytesNeeded;
3010 if (pbEncoded[0] != ASN_INTEGER)
3012 SetLastError(CRYPT_E_ASN1_BADTAG);
3013 ret = FALSE;
3015 else
3016 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3017 lpszStructType, pbEncoded, cbEncoded,
3018 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
3019 if (ret)
3021 if (!pvStructInfo)
3022 *pcbStructInfo = bytesNeeded;
3023 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3024 pvStructInfo, pcbStructInfo, bytesNeeded)))
3026 CRYPT_INTEGER_BLOB *blob;
3028 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3029 pvStructInfo = *(BYTE **)pvStructInfo;
3030 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3031 blob->pbData = (BYTE *)pvStructInfo +
3032 sizeof(CRYPT_INTEGER_BLOB);
3033 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3034 lpszStructType, pbEncoded, cbEncoded,
3035 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3036 &bytesNeeded);
3040 __EXCEPT_PAGE_FAULT
3042 SetLastError(STATUS_ACCESS_VIOLATION);
3043 ret = FALSE;
3045 __ENDTRY
3046 return ret;
3049 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
3050 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3051 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3052 void *pvStructInfo, DWORD *pcbStructInfo)
3054 BOOL ret;
3056 if (pbEncoded[0] == ASN_INTEGER)
3058 DWORD bytesNeeded, dataLen;
3060 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3062 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3064 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3065 if (!pvStructInfo)
3066 *pcbStructInfo = bytesNeeded;
3067 else if (*pcbStructInfo < bytesNeeded)
3069 *pcbStructInfo = bytesNeeded;
3070 SetLastError(ERROR_MORE_DATA);
3071 ret = FALSE;
3073 else
3075 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3077 blob->cbData = dataLen;
3078 assert(blob->pbData);
3079 /* remove leading zero byte if it exists */
3080 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3082 blob->cbData--;
3083 blob->pbData++;
3085 if (blob->cbData)
3087 DWORD i;
3089 for (i = 0; i < blob->cbData; i++)
3091 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3092 dataLen - i - 1);
3098 else
3100 SetLastError(CRYPT_E_ASN1_BADTAG);
3101 ret = FALSE;
3103 return ret;
3106 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3107 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3108 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3110 BOOL ret;
3112 __TRY
3114 DWORD bytesNeeded;
3116 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3117 lpszStructType, pbEncoded, cbEncoded,
3118 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
3120 if (!pvStructInfo)
3121 *pcbStructInfo = bytesNeeded;
3122 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3123 pvStructInfo, pcbStructInfo, bytesNeeded)))
3125 CRYPT_INTEGER_BLOB *blob;
3127 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3128 pvStructInfo = *(BYTE **)pvStructInfo;
3129 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3130 blob->pbData = (BYTE *)pvStructInfo +
3131 sizeof(CRYPT_INTEGER_BLOB);
3132 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3133 lpszStructType, pbEncoded, cbEncoded,
3134 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3135 &bytesNeeded);
3139 __EXCEPT_PAGE_FAULT
3141 SetLastError(STATUS_ACCESS_VIOLATION);
3142 ret = FALSE;
3144 __ENDTRY
3145 return ret;
3148 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3149 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3150 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3152 BOOL ret;
3154 if (!pvStructInfo)
3156 *pcbStructInfo = sizeof(int);
3157 return TRUE;
3159 __TRY
3161 if (pbEncoded[0] == ASN_ENUMERATED)
3163 unsigned int val = 0, i;
3165 if (cbEncoded <= 1)
3167 SetLastError(CRYPT_E_ASN1_EOD);
3168 ret = FALSE;
3170 else if (pbEncoded[1] == 0)
3172 SetLastError(CRYPT_E_ASN1_CORRUPT);
3173 ret = FALSE;
3175 else
3177 /* A little strange looking, but we have to accept a sign byte:
3178 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3179 * assuming a small length is okay here, it has to be in short
3180 * form.
3182 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3184 SetLastError(CRYPT_E_ASN1_LARGE);
3185 return FALSE;
3187 for (i = 0; i < pbEncoded[1]; i++)
3189 val <<= 8;
3190 val |= pbEncoded[2 + i];
3192 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3193 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3195 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3196 pvStructInfo = *(BYTE **)pvStructInfo;
3197 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3201 else
3203 SetLastError(CRYPT_E_ASN1_BADTAG);
3204 ret = FALSE;
3207 __EXCEPT_PAGE_FAULT
3209 SetLastError(STATUS_ACCESS_VIOLATION);
3210 ret = FALSE;
3212 __ENDTRY
3213 return ret;
3216 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3217 * if it fails.
3219 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3220 do { \
3221 BYTE i; \
3223 (word) = 0; \
3224 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3226 if (!isdigit(*(pbEncoded))) \
3228 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3229 ret = FALSE; \
3231 else \
3233 (word) *= 10; \
3234 (word) += *(pbEncoded)++ - '0'; \
3237 } while (0)
3239 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3240 SYSTEMTIME *sysTime)
3242 BOOL ret;
3244 __TRY
3246 ret = TRUE;
3247 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3249 WORD hours, minutes = 0;
3250 BYTE sign = *pbEncoded++;
3252 len--;
3253 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3254 if (ret && hours >= 24)
3256 SetLastError(CRYPT_E_ASN1_CORRUPT);
3257 ret = FALSE;
3259 else if (len >= 2)
3261 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3262 if (ret && minutes >= 60)
3264 SetLastError(CRYPT_E_ASN1_CORRUPT);
3265 ret = FALSE;
3268 if (ret)
3270 if (sign == '+')
3272 sysTime->wHour += hours;
3273 sysTime->wMinute += minutes;
3275 else
3277 if (hours > sysTime->wHour)
3279 sysTime->wDay--;
3280 sysTime->wHour = 24 - (hours - sysTime->wHour);
3282 else
3283 sysTime->wHour -= hours;
3284 if (minutes > sysTime->wMinute)
3286 sysTime->wHour--;
3287 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3289 else
3290 sysTime->wMinute -= minutes;
3295 __EXCEPT_PAGE_FAULT
3297 SetLastError(STATUS_ACCESS_VIOLATION);
3298 ret = FALSE;
3300 __ENDTRY
3301 return ret;
3304 #define MIN_ENCODED_TIME_LENGTH 10
3306 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3307 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3308 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3310 BOOL ret;
3312 if (!pvStructInfo)
3314 *pcbStructInfo = sizeof(FILETIME);
3315 return TRUE;
3317 __TRY
3319 ret = TRUE;
3320 if (pbEncoded[0] == ASN_UTCTIME)
3322 if (cbEncoded <= 1)
3324 SetLastError(CRYPT_E_ASN1_EOD);
3325 ret = FALSE;
3327 else if (pbEncoded[1] > 0x7f)
3329 /* long-form date strings really can't be valid */
3330 SetLastError(CRYPT_E_ASN1_CORRUPT);
3331 ret = FALSE;
3333 else
3335 SYSTEMTIME sysTime = { 0 };
3336 BYTE len = pbEncoded[1];
3338 if (len < MIN_ENCODED_TIME_LENGTH)
3340 SetLastError(CRYPT_E_ASN1_CORRUPT);
3341 ret = FALSE;
3343 else
3345 pbEncoded += 2;
3346 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3347 if (sysTime.wYear >= 50)
3348 sysTime.wYear += 1900;
3349 else
3350 sysTime.wYear += 2000;
3351 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3352 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3353 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3354 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3355 if (ret && len > 0)
3357 if (len >= 2 && isdigit(*pbEncoded) &&
3358 isdigit(*(pbEncoded + 1)))
3359 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3360 sysTime.wSecond);
3361 else if (isdigit(*pbEncoded))
3362 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3363 sysTime.wSecond);
3364 if (ret)
3365 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3366 &sysTime);
3368 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3369 pDecodePara, pvStructInfo, pcbStructInfo,
3370 sizeof(FILETIME))))
3372 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3373 pvStructInfo = *(BYTE **)pvStructInfo;
3374 ret = SystemTimeToFileTime(&sysTime,
3375 (FILETIME *)pvStructInfo);
3380 else
3382 SetLastError(CRYPT_E_ASN1_BADTAG);
3383 ret = FALSE;
3386 __EXCEPT_PAGE_FAULT
3388 SetLastError(STATUS_ACCESS_VIOLATION);
3389 ret = FALSE;
3391 __ENDTRY
3392 return ret;
3395 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3396 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3397 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3399 BOOL ret;
3401 if (!pvStructInfo)
3403 *pcbStructInfo = sizeof(FILETIME);
3404 return TRUE;
3406 __TRY
3408 ret = TRUE;
3409 if (pbEncoded[0] == ASN_GENERALTIME)
3411 if (cbEncoded <= 1)
3413 SetLastError(CRYPT_E_ASN1_EOD);
3414 ret = FALSE;
3416 else if (pbEncoded[1] > 0x7f)
3418 /* long-form date strings really can't be valid */
3419 SetLastError(CRYPT_E_ASN1_CORRUPT);
3420 ret = FALSE;
3422 else
3424 BYTE len = pbEncoded[1];
3426 if (len < MIN_ENCODED_TIME_LENGTH)
3428 SetLastError(CRYPT_E_ASN1_CORRUPT);
3429 ret = FALSE;
3431 else
3433 SYSTEMTIME sysTime = { 0 };
3435 pbEncoded += 2;
3436 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3437 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3438 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3439 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3440 if (ret && len > 0)
3442 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3443 sysTime.wMinute);
3444 if (ret && len > 0)
3445 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3446 sysTime.wSecond);
3447 if (ret && len > 0 && (*pbEncoded == '.' ||
3448 *pbEncoded == ','))
3450 BYTE digits;
3452 pbEncoded++;
3453 len--;
3454 /* workaround macro weirdness */
3455 digits = min(len, 3);
3456 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3457 sysTime.wMilliseconds);
3459 if (ret)
3460 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3461 &sysTime);
3463 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3464 pDecodePara, pvStructInfo, pcbStructInfo,
3465 sizeof(FILETIME))))
3467 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3468 pvStructInfo = *(BYTE **)pvStructInfo;
3469 ret = SystemTimeToFileTime(&sysTime,
3470 (FILETIME *)pvStructInfo);
3475 else
3477 SetLastError(CRYPT_E_ASN1_BADTAG);
3478 ret = FALSE;
3481 __EXCEPT_PAGE_FAULT
3483 SetLastError(STATUS_ACCESS_VIOLATION);
3484 ret = FALSE;
3486 __ENDTRY
3487 return ret;
3490 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3491 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3492 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3494 BOOL ret;
3496 __TRY
3498 if (pbEncoded[0] == ASN_UTCTIME)
3499 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3500 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3501 pcbStructInfo);
3502 else if (pbEncoded[0] == ASN_GENERALTIME)
3503 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3504 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3505 pvStructInfo, pcbStructInfo);
3506 else
3508 SetLastError(CRYPT_E_ASN1_BADTAG);
3509 ret = FALSE;
3512 __EXCEPT_PAGE_FAULT
3514 SetLastError(STATUS_ACCESS_VIOLATION);
3515 ret = FALSE;
3517 __ENDTRY
3518 return ret;
3521 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3522 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3523 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3525 BOOL ret = TRUE;
3527 __TRY
3529 if (pbEncoded[0] == ASN_SEQUENCEOF)
3531 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3533 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3535 BYTE lenBytes;
3536 const BYTE *ptr;
3538 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3539 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3540 cValue = 0;
3541 ptr = pbEncoded + 1 + lenBytes;
3542 remainingLen = dataLen;
3543 while (ret && remainingLen)
3545 DWORD nextLen;
3547 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3548 if (ret)
3550 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3552 remainingLen -= 1 + nextLenBytes + nextLen;
3553 ptr += 1 + nextLenBytes + nextLen;
3554 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3555 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3556 bytesNeeded += 1 + nextLenBytes + nextLen;
3557 cValue++;
3560 if (ret)
3562 CRYPT_SEQUENCE_OF_ANY *seq;
3563 BYTE *nextPtr;
3564 DWORD i;
3566 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3567 pvStructInfo, pcbStructInfo, bytesNeeded)))
3569 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3570 pvStructInfo = *(BYTE **)pvStructInfo;
3571 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3572 seq->cValue = cValue;
3573 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3574 sizeof(*seq));
3575 nextPtr = (BYTE *)seq->rgValue +
3576 cValue * sizeof(CRYPT_DER_BLOB);
3577 ptr = pbEncoded + 1 + lenBytes;
3578 remainingLen = dataLen;
3579 i = 0;
3580 while (ret && remainingLen)
3582 DWORD nextLen;
3584 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3585 if (ret)
3587 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3589 seq->rgValue[i].cbData = 1 + nextLenBytes +
3590 nextLen;
3591 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3592 seq->rgValue[i].pbData = (BYTE *)ptr;
3593 else
3595 seq->rgValue[i].pbData = nextPtr;
3596 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3597 nextLen);
3598 nextPtr += 1 + nextLenBytes + nextLen;
3600 remainingLen -= 1 + nextLenBytes + nextLen;
3601 ptr += 1 + nextLenBytes + nextLen;
3602 i++;
3609 else
3611 SetLastError(CRYPT_E_ASN1_BADTAG);
3612 ret = FALSE;
3615 __EXCEPT_PAGE_FAULT
3617 SetLastError(STATUS_ACCESS_VIOLATION);
3618 ret = FALSE;
3620 __ENDTRY
3621 return ret;
3624 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3625 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3626 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3628 BOOL ret;
3630 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3632 DWORD bytesNeeded, dataLen;
3634 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3636 struct AsnArrayDescriptor arrayDesc = {
3637 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3638 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3639 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3640 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3642 if (dataLen)
3644 DWORD nameLen;
3646 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3647 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3648 0, NULL, NULL, &nameLen, NULL);
3649 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3651 else
3652 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3653 if (!pvStructInfo)
3654 *pcbStructInfo = bytesNeeded;
3655 else if (*pcbStructInfo < bytesNeeded)
3657 *pcbStructInfo = bytesNeeded;
3658 SetLastError(ERROR_MORE_DATA);
3659 ret = FALSE;
3661 else
3663 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3665 if (dataLen)
3667 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3668 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3669 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3670 0, NULL, &name->u.FullName, pcbStructInfo,
3671 name->u.FullName.rgAltEntry);
3673 else
3674 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3678 else
3680 SetLastError(CRYPT_E_ASN1_BADTAG);
3681 ret = FALSE;
3683 return ret;
3686 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3687 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3688 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3690 struct AsnDecodeSequenceItem items[] = {
3691 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3692 DistPointName), CRYPT_AsnDecodeDistPointName,
3693 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3694 DistPointName.u.FullName.rgAltEntry), 0 },
3695 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3696 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3697 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3698 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3699 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3700 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3702 BOOL ret;
3704 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3705 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3706 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3707 return ret;
3710 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3711 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3712 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3714 BOOL ret;
3716 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3717 pDecodePara, pvStructInfo, *pcbStructInfo);
3719 __TRY
3721 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3722 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3723 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3725 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3726 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3728 __EXCEPT_PAGE_FAULT
3730 SetLastError(STATUS_ACCESS_VIOLATION);
3731 ret = FALSE;
3733 __ENDTRY
3734 return ret;
3737 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3738 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3739 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3741 BOOL ret;
3743 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3744 pDecodePara, pvStructInfo, *pcbStructInfo);
3746 __TRY
3748 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3749 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3751 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3752 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3754 __EXCEPT_PAGE_FAULT
3756 SetLastError(STATUS_ACCESS_VIOLATION);
3757 ret = FALSE;
3759 __ENDTRY
3760 return ret;
3763 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3764 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3765 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3767 BOOL ret;
3769 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3770 pDecodePara, pvStructInfo, *pcbStructInfo);
3772 __TRY
3774 struct AsnDecodeSequenceItem items[] = {
3775 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3776 DistPointName), CRYPT_AsnDecodeDistPointName,
3777 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3778 offsetof(CRL_ISSUING_DIST_POINT,
3779 DistPointName.u.FullName.rgAltEntry), 0 },
3780 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3781 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3782 FALSE, 0 },
3783 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3784 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3785 FALSE, 0 },
3786 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3787 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3788 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3789 OnlySomeReasonFlags.pbData), 0 },
3790 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3791 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3794 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3795 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3796 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3798 __EXCEPT_PAGE_FAULT
3800 SetLastError(STATUS_ACCESS_VIOLATION);
3801 ret = FALSE;
3803 __ENDTRY
3804 return ret;
3807 static BOOL WINAPI CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType,
3808 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3809 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3811 BOOL ret;
3812 struct AsnDecodeSequenceItem items[] = {
3813 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
3814 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
3815 Issuer.pbData) },
3816 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
3817 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
3818 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
3820 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3821 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3823 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3824 pDecodePara, pvStructInfo, *pcbStructInfo);
3826 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3827 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3828 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
3829 issuerSerial ? issuerSerial->Issuer.pbData : NULL);
3830 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
3832 SetLastError(CRYPT_E_ASN1_CORRUPT);
3833 ret = FALSE;
3835 TRACE("returning %d\n", ret);
3836 return ret;
3839 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfoInternal(
3840 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3841 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3842 void *pvStructInfo, DWORD *pcbStructInfo)
3844 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
3845 struct AsnDecodeSequenceItem items[] = {
3846 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
3847 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3848 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
3849 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
3850 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
3851 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
3852 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3853 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
3854 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
3855 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
3856 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3857 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
3858 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
3859 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3860 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
3861 HashEncryptionAlgorithm.pszObjId), 0 },
3862 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
3863 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
3864 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
3865 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
3866 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
3867 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3868 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
3870 BOOL ret;
3872 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3873 pDecodePara, pvStructInfo, *pcbStructInfo);
3875 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3876 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3877 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
3878 info ? info->Issuer.pbData : NULL);
3879 return ret;
3882 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
3883 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3884 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3886 BOOL ret = FALSE;
3888 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3889 pDecodePara, pvStructInfo, *pcbStructInfo);
3891 __TRY
3893 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType,
3894 lpszStructType, pbEncoded, cbEncoded,
3895 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
3896 if (ret && pvStructInfo)
3898 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3899 pcbStructInfo, *pcbStructInfo);
3900 if (ret)
3902 CMSG_SIGNER_INFO *info;
3904 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3905 pvStructInfo = *(BYTE **)pvStructInfo;
3906 info = (CMSG_SIGNER_INFO *)pvStructInfo;
3907 info->Issuer.pbData = ((BYTE *)info +
3908 sizeof(CMSG_SIGNER_INFO));
3909 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType,
3910 lpszStructType, pbEncoded, cbEncoded,
3911 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
3912 pcbStructInfo);
3916 __EXCEPT_PAGE_FAULT
3918 SetLastError(STATUS_ACCESS_VIOLATION);
3920 __ENDTRY
3921 TRACE("returning %d\n", ret);
3922 return ret;
3925 static BOOL WINAPI CRYPT_DecodeSignerArray(DWORD dwCertEncodingType,
3926 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3927 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3929 BOOL ret;
3930 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
3931 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
3932 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
3933 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
3935 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3936 pDecodePara, pvStructInfo, *pcbStructInfo);
3938 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3939 pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
3940 return ret;
3943 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
3944 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3945 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
3947 BOOL ret = FALSE;
3948 struct AsnDecodeSequenceItem items[] = {
3949 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version), CRYPT_AsnDecodeInt,
3950 sizeof(DWORD), FALSE, FALSE, 0, 0 },
3951 /* Placeholder for the hash algorithms - redundant with those in the
3952 * signers, so just ignore them.
3954 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
3955 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
3956 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
3957 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
3958 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
3959 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
3960 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
3961 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
3962 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
3963 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
3964 sizeof(struct GenericArray), TRUE, TRUE,
3965 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
3966 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
3967 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
3968 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
3971 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3972 pDecodePara, signedInfo, *pcbSignedInfo);
3974 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3975 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
3976 pDecodePara, signedInfo, pcbSignedInfo, NULL);
3977 TRACE("returning %d\n", ret);
3978 return ret;
3981 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
3982 LPCSTR lpszStructType)
3984 CryptDecodeObjectExFunc decodeFunc = NULL;
3986 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3987 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3989 SetLastError(ERROR_FILE_NOT_FOUND);
3990 return NULL;
3992 if (!HIWORD(lpszStructType))
3994 switch (LOWORD(lpszStructType))
3996 case (WORD)X509_CERT:
3997 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3998 break;
3999 case (WORD)X509_CERT_TO_BE_SIGNED:
4000 decodeFunc = CRYPT_AsnDecodeCert;
4001 break;
4002 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
4003 decodeFunc = CRYPT_AsnDecodeCRL;
4004 break;
4005 case (WORD)X509_EXTENSIONS:
4006 decodeFunc = CRYPT_AsnDecodeExtensions;
4007 break;
4008 case (WORD)X509_NAME_VALUE:
4009 decodeFunc = CRYPT_AsnDecodeNameValue;
4010 break;
4011 case (WORD)X509_NAME:
4012 decodeFunc = CRYPT_AsnDecodeName;
4013 break;
4014 case (WORD)X509_PUBLIC_KEY_INFO:
4015 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4016 break;
4017 case (WORD)X509_AUTHORITY_KEY_ID:
4018 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4019 break;
4020 case (WORD)X509_ALTERNATE_NAME:
4021 decodeFunc = CRYPT_AsnDecodeAltName;
4022 break;
4023 case (WORD)X509_BASIC_CONSTRAINTS:
4024 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4025 break;
4026 case (WORD)X509_BASIC_CONSTRAINTS2:
4027 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4028 break;
4029 case (WORD)RSA_CSP_PUBLICKEYBLOB:
4030 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4031 break;
4032 case (WORD)X509_UNICODE_NAME:
4033 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4034 break;
4035 case (WORD)PKCS_ATTRIBUTE:
4036 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4037 break;
4038 case (WORD)X509_UNICODE_NAME_VALUE:
4039 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4040 break;
4041 case (WORD)X509_OCTET_STRING:
4042 decodeFunc = CRYPT_AsnDecodeOctets;
4043 break;
4044 case (WORD)X509_BITS:
4045 case (WORD)X509_KEY_USAGE:
4046 decodeFunc = CRYPT_AsnDecodeBits;
4047 break;
4048 case (WORD)X509_INTEGER:
4049 decodeFunc = CRYPT_AsnDecodeInt;
4050 break;
4051 case (WORD)X509_MULTI_BYTE_INTEGER:
4052 decodeFunc = CRYPT_AsnDecodeInteger;
4053 break;
4054 case (WORD)X509_MULTI_BYTE_UINT:
4055 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4056 break;
4057 case (WORD)X509_ENUMERATED:
4058 decodeFunc = CRYPT_AsnDecodeEnumerated;
4059 break;
4060 case (WORD)X509_CHOICE_OF_TIME:
4061 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4062 break;
4063 case (WORD)X509_AUTHORITY_KEY_ID2:
4064 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4065 break;
4066 case (WORD)PKCS_CONTENT_INFO:
4067 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4068 break;
4069 case (WORD)X509_SEQUENCE_OF_ANY:
4070 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4071 break;
4072 case (WORD)PKCS_UTC_TIME:
4073 decodeFunc = CRYPT_AsnDecodeUtcTime;
4074 break;
4075 case (WORD)X509_CRL_DIST_POINTS:
4076 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4077 break;
4078 case (WORD)X509_ENHANCED_KEY_USAGE:
4079 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4080 break;
4081 case (WORD)PKCS_ATTRIBUTES:
4082 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4083 break;
4084 case (WORD)X509_ISSUING_DIST_POINT:
4085 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4086 break;
4087 case (WORD)PKCS7_SIGNER_INFO:
4088 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4089 break;
4092 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4093 decodeFunc = CRYPT_AsnDecodeExtensions;
4094 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4095 decodeFunc = CRYPT_AsnDecodeUtcTime;
4096 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4097 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4098 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4099 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4100 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4101 decodeFunc = CRYPT_AsnDecodeEnumerated;
4102 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4103 decodeFunc = CRYPT_AsnDecodeBits;
4104 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4105 decodeFunc = CRYPT_AsnDecodeOctets;
4106 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4107 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4108 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4109 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4110 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4111 decodeFunc = CRYPT_AsnDecodeAltName;
4112 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4113 decodeFunc = CRYPT_AsnDecodeAltName;
4114 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4115 decodeFunc = CRYPT_AsnDecodeAltName;
4116 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4117 decodeFunc = CRYPT_AsnDecodeAltName;
4118 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4119 decodeFunc = CRYPT_AsnDecodeAltName;
4120 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4121 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4122 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4123 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4124 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4125 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4126 return decodeFunc;
4129 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4130 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4132 static HCRYPTOIDFUNCSET set = NULL;
4133 CryptDecodeObjectFunc decodeFunc = NULL;
4135 if (!set)
4136 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4137 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4138 (void **)&decodeFunc, hFunc);
4139 return decodeFunc;
4142 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4143 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4145 static HCRYPTOIDFUNCSET set = NULL;
4146 CryptDecodeObjectExFunc decodeFunc = NULL;
4148 if (!set)
4149 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4150 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4151 (void **)&decodeFunc, hFunc);
4152 return decodeFunc;
4155 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4156 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4157 DWORD *pcbStructInfo)
4159 BOOL ret = FALSE;
4160 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4161 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4162 HCRYPTOIDFUNCADDR hFunc = NULL;
4164 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4165 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4166 pvStructInfo, pcbStructInfo);
4168 if (!pvStructInfo && !pcbStructInfo)
4170 SetLastError(ERROR_INVALID_PARAMETER);
4171 return FALSE;
4173 if (!cbEncoded)
4175 SetLastError(CRYPT_E_ASN1_EOD);
4176 return FALSE;
4178 if (cbEncoded > MAX_ENCODED_LEN)
4180 SetLastError(CRYPT_E_ASN1_LARGE);
4181 return FALSE;
4184 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4185 lpszStructType)))
4187 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4188 debugstr_a(lpszStructType));
4189 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4190 lpszStructType, &hFunc);
4191 if (!pCryptDecodeObject)
4192 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4193 lpszStructType, &hFunc);
4195 if (pCryptDecodeObject)
4196 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4197 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4198 else if (pCryptDecodeObjectEx)
4199 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4200 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4201 pvStructInfo, pcbStructInfo);
4202 if (hFunc)
4203 CryptFreeOIDFunctionAddress(hFunc, 0);
4204 TRACE_(crypt)("returning %d\n", ret);
4205 return ret;
4208 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4209 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4210 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4212 BOOL ret = FALSE;
4213 CryptDecodeObjectExFunc decodeFunc;
4214 HCRYPTOIDFUNCADDR hFunc = NULL;
4216 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4217 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4218 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4220 if (!pvStructInfo && !pcbStructInfo)
4222 SetLastError(ERROR_INVALID_PARAMETER);
4223 return FALSE;
4225 if (!cbEncoded)
4227 SetLastError(CRYPT_E_ASN1_EOD);
4228 return FALSE;
4230 if (cbEncoded > MAX_ENCODED_LEN)
4232 SetLastError(CRYPT_E_ASN1_LARGE);
4233 return FALSE;
4236 SetLastError(NOERROR);
4237 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4238 *(BYTE **)pvStructInfo = NULL;
4239 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4240 if (!decodeFunc)
4242 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4243 debugstr_a(lpszStructType));
4244 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4245 &hFunc);
4247 if (decodeFunc)
4248 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4249 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4250 else
4252 CryptDecodeObjectFunc pCryptDecodeObject =
4253 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4255 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4256 * directly, as that could cause an infinite loop.
4258 if (pCryptDecodeObject)
4260 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4262 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4263 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4264 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4265 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4266 ret = pCryptDecodeObject(dwCertEncodingType,
4267 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4268 *(BYTE **)pvStructInfo, pcbStructInfo);
4270 else
4271 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4272 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4275 if (hFunc)
4276 CryptFreeOIDFunctionAddress(hFunc, 0);
4277 TRACE_(crypt)("returning %d\n", ret);
4278 return ret;