shell32: Fix the file version string of the version resource.
[wine/multimedia.git] / dlls / crypt32 / decode.c
blob04e2df2be7075658bff22c1c6cb1b62de39a356e
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 "excpt.h"
44 #include "wincrypt.h"
45 #include "winnls.h"
46 #include "winreg.h"
47 #include "snmp.h"
48 #include "wine/debug.h"
49 #include "wine/exception.h"
50 #include "crypt32_private.h"
52 /* This is a bit arbitrary, but to set some limit: */
53 #define MAX_ENCODED_LEN 0x02000000
55 #define ASN_FLAGS_MASK 0xe0
56 #define ASN_TYPE_MASK 0x1f
58 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
60 struct GenericArray
62 DWORD cItems;
63 BYTE *rgItems;
66 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
67 DWORD, DWORD, void *, DWORD *);
68 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
69 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
71 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
72 * The dwCertEncodingType and lpszStructType are ignored by the built-in
73 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
74 * since it must call functions in external DLLs that follow these signatures.
76 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
77 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
78 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
79 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
80 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
81 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
82 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
83 * time, doesn't do memory allocation, and doesn't do exception handling.
84 * (This isn't intended to be the externally-called one.)
86 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
87 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
88 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
89 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
90 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
92 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
93 /* Internal function */
94 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
95 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
96 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
97 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
98 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
99 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
100 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
101 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
102 * member has been initialized, doesn't do exception handling, and doesn't do
103 * memory allocation.
105 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
106 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
107 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
108 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
109 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
110 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
111 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
112 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
113 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
114 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
115 * member has been initialized, doesn't do exception handling, and doesn't do
116 * memory allocation.
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 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
128 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
129 DWORD *pcbStructInfo)
131 static HCRYPTOIDFUNCSET set = NULL;
132 BOOL ret = FALSE;
133 CryptDecodeObjectFunc pCryptDecodeObject;
134 HCRYPTOIDFUNCADDR hFunc;
136 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType,
137 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
138 pvStructInfo, pcbStructInfo);
140 if (!pvStructInfo && !pcbStructInfo)
142 SetLastError(ERROR_INVALID_PARAMETER);
143 return FALSE;
146 /* Try registered DLL first.. */
147 if (!set)
148 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
149 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
150 (void **)&pCryptDecodeObject, &hFunc);
151 if (pCryptDecodeObject)
153 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
154 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
155 CryptFreeOIDFunctionAddress(hFunc, 0);
157 else
159 /* If not, use CryptDecodeObjectEx */
160 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
161 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
163 return ret;
166 /* Gets the number of length bytes from the given (leading) length byte */
167 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
169 /* Helper function to get the encoded length of the data starting at pbEncoded,
170 * where pbEncoded[0] is the tag. If the data are too short to contain a
171 * length or if the length is too large for cbEncoded, sets an appropriate
172 * error code and returns FALSE.
174 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
175 DWORD *len)
177 BOOL ret;
179 if (cbEncoded <= 1)
181 SetLastError(CRYPT_E_ASN1_CORRUPT);
182 ret = FALSE;
184 else if (pbEncoded[1] <= 0x7f)
186 if (pbEncoded[1] + 1 > cbEncoded)
188 SetLastError(CRYPT_E_ASN1_EOD);
189 ret = FALSE;
191 else
193 *len = pbEncoded[1];
194 ret = TRUE;
197 else
199 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
201 if (lenLen > sizeof(DWORD) + 1)
203 SetLastError(CRYPT_E_ASN1_LARGE);
204 ret = FALSE;
206 else if (lenLen + 2 > cbEncoded)
208 SetLastError(CRYPT_E_ASN1_CORRUPT);
209 ret = FALSE;
211 else
213 DWORD out = 0;
215 pbEncoded += 2;
216 while (--lenLen)
218 out <<= 8;
219 out |= *pbEncoded++;
221 if (out + lenLen + 1 > cbEncoded)
223 SetLastError(CRYPT_E_ASN1_EOD);
224 ret = FALSE;
226 else
228 *len = out;
229 ret = TRUE;
233 return ret;
236 /* Helper function to check *pcbStructInfo, set it to the required size, and
237 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
238 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
239 * pointer to the newly allocated memory.
241 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
242 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
243 DWORD bytesNeeded)
245 BOOL ret = TRUE;
247 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
249 if (pDecodePara && pDecodePara->pfnAlloc)
250 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
251 else
252 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
253 if (!*(BYTE **)pvStructInfo)
254 ret = FALSE;
255 else
256 *pcbStructInfo = bytesNeeded;
258 else if (*pcbStructInfo < bytesNeeded)
260 *pcbStructInfo = bytesNeeded;
261 SetLastError(ERROR_MORE_DATA);
262 ret = FALSE;
264 return ret;
267 /* tag:
268 * The expected tag of the item. If tag is 0, decodeFunc is called
269 * regardless of the tag value seen.
270 * offset:
271 * A sequence is decoded into a struct. The offset member is the
272 * offset of this item within that struct.
273 * decodeFunc:
274 * The decoder function to use. If this is NULL, then the member isn't
275 * decoded, but minSize space is reserved for it.
276 * minSize:
277 * The minimum amount of space occupied after decoding. You must set this.
278 * optional:
279 * If true, and the tag doesn't match the expected tag for this item,
280 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
281 * filled with 0 for this member.
282 * hasPointer, pointerOffset, minSize:
283 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
284 * the offset within the (outer) struct of the data pointer (or to the
285 * first data pointer, if more than one exist).
286 * size:
287 * Used by CRYPT_AsnDecodeSequence, not for your use.
289 struct AsnDecodeSequenceItem
291 BYTE tag;
292 DWORD offset;
293 CryptDecodeObjectExFunc decodeFunc;
294 DWORD minSize;
295 BOOL optional;
296 BOOL hasPointer;
297 DWORD pointerOffset;
298 DWORD size;
301 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
302 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
303 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData)
305 BOOL ret;
306 DWORD i;
307 const BYTE *ptr;
309 ptr = pbEncoded + 1 + GET_LEN_BYTES(pbEncoded[1]);
310 for (i = 0, ret = TRUE; ret && i < cItem; i++)
312 if (cbEncoded - (ptr - pbEncoded) != 0)
314 DWORD nextItemLen;
316 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
317 &nextItemLen)))
319 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
321 if (ptr[0] == items[i].tag || !items[i].tag)
323 if (nextData && pvStructInfo && items[i].hasPointer)
325 TRACE("Setting next pointer to %p\n",
326 nextData);
327 *(BYTE **)((BYTE *)pvStructInfo +
328 items[i].pointerOffset) = nextData;
330 if (items[i].decodeFunc)
332 if (pvStructInfo)
333 TRACE("decoding item %ld\n", i);
334 else
335 TRACE("sizing item %ld\n", i);
336 ret = items[i].decodeFunc(dwCertEncodingType,
337 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
338 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
339 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
340 : NULL, &items[i].size);
341 if (ret)
343 if (nextData && items[i].hasPointer &&
344 items[i].size > items[i].minSize)
346 nextData += items[i].size - items[i].minSize;
347 /* align nextData to DWORD boundaries */
348 if (items[i].size % sizeof(DWORD))
349 nextData += sizeof(DWORD) - items[i].size %
350 sizeof(DWORD);
352 /* Account for alignment padding */
353 if (items[i].size % sizeof(DWORD))
354 items[i].size += sizeof(DWORD) -
355 items[i].size % sizeof(DWORD);
356 ptr += 1 + nextItemLenBytes + nextItemLen;
358 else if (items[i].optional &&
359 GetLastError() == CRYPT_E_ASN1_BADTAG)
361 TRACE("skipping optional item %ld\n", i);
362 items[i].size = items[i].minSize;
363 SetLastError(NOERROR);
364 ret = TRUE;
366 else
367 TRACE("item %ld failed: %08lx\n", i,
368 GetLastError());
370 else
371 items[i].size = items[i].minSize;
373 else if (items[i].optional)
375 TRACE("skipping optional item %ld\n", i);
376 items[i].size = items[i].minSize;
378 else
380 TRACE("tag %02x doesn't match expected %02x\n",
381 ptr[0], items[i].tag);
382 SetLastError(CRYPT_E_ASN1_BADTAG);
383 ret = FALSE;
387 else if (items[i].optional)
389 TRACE("missing optional item %ld, skipping\n", i);
390 items[i].size = items[i].minSize;
392 else
394 TRACE("not enough bytes for item %ld, failing\n", i);
395 SetLastError(CRYPT_E_ASN1_CORRUPT);
396 ret = FALSE;
399 if (cbEncoded - (ptr - pbEncoded) != 0)
401 TRACE("%ld remaining bytes, failing\n", cbEncoded -
402 (ptr - pbEncoded));
403 SetLastError(CRYPT_E_ASN1_CORRUPT);
404 ret = FALSE;
406 return ret;
409 /* This decodes an arbitrary sequence into a contiguous block of memory
410 * (basically, a struct.) Each element being decoded is described by a struct
411 * AsnDecodeSequenceItem, see above.
412 * startingPointer is an optional pointer to the first place where dynamic
413 * data will be stored. If you know the starting offset, you may pass it
414 * here. Otherwise, pass NULL, and one will be inferred from the items.
415 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
416 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
418 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
419 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
420 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
421 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
423 BOOL ret;
425 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded,
426 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
427 startingPointer);
429 if (pbEncoded[0] == ASN_SEQUENCE)
431 DWORD dataLen;
433 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
435 DWORD i;
437 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
438 cbEncoded, dwFlags, NULL, NULL);
439 if (ret)
441 DWORD bytesNeeded = 0, structSize = 0;
443 for (i = 0; i < cItem; i++)
445 bytesNeeded += items[i].size;
446 structSize += items[i].minSize;
448 if (!pvStructInfo)
449 *pcbStructInfo = bytesNeeded;
450 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
451 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
453 BYTE *nextData;
455 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
456 pvStructInfo = *(BYTE **)pvStructInfo;
457 if (startingPointer)
458 nextData = (BYTE *)startingPointer;
459 else
460 nextData = (BYTE *)pvStructInfo + structSize;
461 memset(pvStructInfo, 0, structSize);
462 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
463 pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
468 else
470 SetLastError(CRYPT_E_ASN1_BADTAG);
471 ret = FALSE;
473 TRACE("returning %d (%08lx)\n", ret, GetLastError());
474 return ret;
477 /* tag:
478 * The expected tag of the entire encoded array (usually a variant
479 * of ASN_SETOF or ASN_SEQUENCEOF.)
480 * decodeFunc:
481 * used to decode each item in the array
482 * itemSize:
483 * is the minimum size of each decoded item
484 * hasPointer:
485 * indicates whether each item has a dynamic pointer
486 * pointerOffset:
487 * indicates the offset within itemSize at which the pointer exists
489 struct AsnArrayDescriptor
491 BYTE tag;
492 CryptDecodeObjectExFunc decodeFunc;
493 DWORD itemSize;
494 BOOL hasPointer;
495 DWORD pointerOffset;
498 struct AsnArrayItemSize
500 DWORD encodedLen;
501 DWORD size;
504 /* Decodes an array of like types into a struct GenericArray.
505 * The layout and decoding of the array are described by a struct
506 * AsnArrayDescriptor.
508 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
509 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
510 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
511 void *startingPointer)
513 BOOL ret = TRUE;
515 TRACE("%p, %p, %ld, %08lx, %p, %p, %ld, %p\n", arrayDesc, pbEncoded,
516 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
517 startingPointer);
519 if (pbEncoded[0] == arrayDesc->tag)
521 DWORD dataLen;
523 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
525 DWORD bytesNeeded, cItems = 0;
526 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
527 /* There can be arbitrarily many items, but there is often only one.
529 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
531 bytesNeeded = sizeof(struct GenericArray);
532 if (dataLen)
534 const BYTE *ptr;
536 for (ptr = pbEncoded + 1 + lenBytes; ret &&
537 ptr - pbEncoded - 1 - lenBytes < dataLen; )
539 DWORD itemLenBytes, itemDataLen, size;
541 itemLenBytes = GET_LEN_BYTES(ptr[1]);
542 /* Each item decoded may not tolerate extraneous bytes, so
543 * get the length of the next element and pass it directly.
545 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
546 &itemDataLen);
547 if (ret)
548 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
549 1 + itemLenBytes + itemDataLen,
550 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
551 &size);
552 if (ret)
554 DWORD nextLen;
556 cItems++;
557 if (itemSizes != &itemSize)
558 itemSizes = CryptMemRealloc(itemSizes,
559 cItems * sizeof(struct AsnArrayItemSize));
560 else
562 itemSizes =
563 CryptMemAlloc(
564 cItems * sizeof(struct AsnArrayItemSize));
565 if (itemSizes)
566 memcpy(itemSizes, &itemSize, sizeof(itemSize));
568 if (itemSizes)
570 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
571 + itemDataLen;
572 itemSizes[cItems - 1].size = size;
573 bytesNeeded += size;
574 ret = CRYPT_GetLen(ptr,
575 cbEncoded - (ptr - pbEncoded), &nextLen);
576 if (ret)
577 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
579 else
580 ret = FALSE;
584 if (ret)
586 if (!pvStructInfo)
587 *pcbStructInfo = bytesNeeded;
588 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
589 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
591 DWORD i;
592 BYTE *nextData;
593 const BYTE *ptr;
594 struct GenericArray *array;
596 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
597 pvStructInfo = *(BYTE **)pvStructInfo;
598 array = (struct GenericArray *)pvStructInfo;
599 array->cItems = cItems;
600 if (startingPointer)
601 array->rgItems = startingPointer;
602 else
603 array->rgItems = (BYTE *)array +
604 sizeof(struct GenericArray);
605 nextData = (BYTE *)array->rgItems +
606 array->cItems * arrayDesc->itemSize;
607 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
608 i < cItems && ptr - pbEncoded - 1 - lenBytes <
609 dataLen; i++)
611 if (arrayDesc->hasPointer)
612 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
613 + arrayDesc->pointerOffset) = nextData;
614 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
615 itemSizes[i].encodedLen,
616 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
617 array->rgItems + i * arrayDesc->itemSize,
618 &itemSizes[i].size);
619 if (ret)
621 DWORD nextLen;
623 nextData += itemSizes[i].size - arrayDesc->itemSize;
624 ret = CRYPT_GetLen(ptr,
625 cbEncoded - (ptr - pbEncoded), &nextLen);
626 if (ret)
627 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
632 if (itemSizes != &itemSize)
633 CryptMemFree(itemSizes);
636 else
638 SetLastError(CRYPT_E_ASN1_BADTAG);
639 ret = FALSE;
641 return ret;
644 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
645 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
646 * to CRYPT_E_ASN1_CORRUPT.
647 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
648 * set!
650 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
651 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
652 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
654 BOOL ret;
655 DWORD dataLen;
657 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
659 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
660 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
662 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
663 bytesNeeded += 1 + lenBytes + dataLen;
665 if (!pvStructInfo)
666 *pcbStructInfo = bytesNeeded;
667 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
668 pvStructInfo, pcbStructInfo, bytesNeeded)))
670 CRYPT_DER_BLOB *blob;
672 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
673 pvStructInfo = *(BYTE **)pvStructInfo;
674 blob = (CRYPT_DER_BLOB *)pvStructInfo;
675 blob->cbData = 1 + lenBytes + dataLen;
676 if (blob->cbData)
678 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
679 blob->pbData = (BYTE *)pbEncoded;
680 else
682 assert(blob->pbData);
683 memcpy(blob->pbData, pbEncoded, blob->cbData);
686 else
688 SetLastError(CRYPT_E_ASN1_CORRUPT);
689 ret = FALSE;
693 return ret;
696 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
697 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
698 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
699 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
701 BOOL ret;
703 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
704 pDecodePara, pvStructInfo, *pcbStructInfo);
706 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
707 * place.
709 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
710 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
711 pvStructInfo, pcbStructInfo);
712 if (ret && pvStructInfo)
714 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
716 if (blob->cbData)
718 DWORD i;
719 BYTE temp;
721 for (i = 0; i < blob->cbData / 2; i++)
723 temp = blob->pbData[i];
724 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
725 blob->pbData[blob->cbData - i - 1] = temp;
729 TRACE("returning %d (%08lx)\n", ret, GetLastError());
730 return ret;
733 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
734 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
735 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
737 BOOL ret = TRUE;
739 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
740 pDecodePara, pvStructInfo, *pcbStructInfo);
742 __TRY
744 struct AsnDecodeSequenceItem items[] = {
745 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
746 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
747 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
748 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
749 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
750 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
751 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
752 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
753 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
754 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
757 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
758 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
759 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
760 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
761 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
763 __EXCEPT_PAGE_FAULT
765 SetLastError(STATUS_ACCESS_VIOLATION);
766 ret = FALSE;
768 __ENDTRY
770 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
771 return ret;
774 /* Internal function */
775 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
776 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
777 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
779 BOOL ret;
780 DWORD dataLen;
782 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
784 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
786 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
787 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
788 pvStructInfo, pcbStructInfo);
790 return ret;
793 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
794 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
795 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
797 BOOL ret;
799 struct AsnDecodeSequenceItem items[] = {
800 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
801 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
802 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
803 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
806 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
807 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
808 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
809 return ret;
812 /* Internal function */
813 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
814 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
815 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
817 BOOL ret;
818 DWORD dataLen;
820 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
822 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
824 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
825 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
826 pDecodePara, pvStructInfo, pcbStructInfo);
828 return ret;
831 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
832 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
833 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
835 BOOL ret = TRUE;
836 struct AsnDecodeSequenceItem items[] = {
837 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
838 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
839 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
840 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
841 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
842 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
843 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
844 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
845 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
846 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
847 Issuer.pbData) },
848 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
849 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
850 FALSE, 0 },
851 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
852 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
853 Subject.pbData) },
854 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
855 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
856 FALSE, TRUE, offsetof(CERT_INFO,
857 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
858 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
859 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
860 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
861 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
862 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
863 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
864 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
865 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
866 offsetof(CERT_INFO, rgExtension), 0 },
869 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
870 pDecodePara, pvStructInfo, *pcbStructInfo);
872 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
873 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
874 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
876 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
877 return ret;
880 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
881 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
882 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
884 BOOL ret = TRUE;
886 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
887 pDecodePara, pvStructInfo, *pcbStructInfo);
889 __TRY
891 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
892 DWORD size = 0;
894 /* First try to decode it as a signed cert. */
895 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
896 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
897 (BYTE *)&signedCert, &size);
898 if (ret)
900 size = 0;
901 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
902 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
903 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
904 pcbStructInfo);
905 LocalFree(signedCert);
907 /* Failing that, try it as an unsigned cert */
908 if (!ret)
910 size = 0;
911 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
912 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
913 pDecodePara, pvStructInfo, pcbStructInfo);
916 __EXCEPT_PAGE_FAULT
918 SetLastError(STATUS_ACCESS_VIOLATION);
919 ret = FALSE;
921 __ENDTRY
923 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
924 return ret;
927 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
928 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
929 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
931 BOOL ret;
932 struct AsnDecodeSequenceItem items[] = {
933 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
934 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
935 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
936 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
937 sizeof(FILETIME), FALSE, FALSE, 0 },
938 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
939 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
940 offsetof(CRL_ENTRY, rgExtension), 0 },
942 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
944 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
945 *pcbStructInfo);
947 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
948 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
949 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
950 return ret;
953 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
954 * been set prior to calling.
956 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
957 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
958 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
960 BOOL ret;
961 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
962 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
963 offsetof(CRL_ENTRY, SerialNumber.pbData) };
964 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
966 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
967 pDecodePara, pvStructInfo, *pcbStructInfo);
969 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
970 pDecodePara, pvStructInfo, pcbStructInfo,
971 entries ? entries->rgItems : NULL);
972 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
973 return ret;
976 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
977 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
978 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
980 struct AsnDecodeSequenceItem items[] = {
981 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
982 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
983 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
984 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
985 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
986 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
987 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
988 Issuer.pbData) },
989 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
990 sizeof(FILETIME), FALSE, FALSE, 0 },
991 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
992 sizeof(FILETIME), TRUE, FALSE, 0 },
993 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
994 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
995 offsetof(CRL_INFO, rgCRLEntry), 0 },
996 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
997 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
998 offsetof(CRL_INFO, rgExtension), 0 },
1000 BOOL ret = TRUE;
1002 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1003 pDecodePara, pvStructInfo, *pcbStructInfo);
1005 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1006 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1007 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1009 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1010 return ret;
1013 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1014 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1015 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1017 BOOL ret = TRUE;
1019 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1020 pDecodePara, pvStructInfo, *pcbStructInfo);
1022 __TRY
1024 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1025 DWORD size = 0;
1027 /* First try to decode it as a signed crl. */
1028 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1029 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1030 (BYTE *)&signedCrl, &size);
1031 if (ret)
1033 size = 0;
1034 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1035 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1036 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1037 pvStructInfo, pcbStructInfo);
1038 LocalFree(signedCrl);
1040 /* Failing that, try it as an unsigned crl */
1041 if (!ret)
1043 size = 0;
1044 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1045 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1046 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1049 __EXCEPT_PAGE_FAULT
1051 SetLastError(STATUS_ACCESS_VIOLATION);
1052 ret = FALSE;
1054 __ENDTRY
1056 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1057 return ret;
1060 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1061 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1062 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1064 BOOL ret = TRUE;
1066 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1067 pDecodePara, pvStructInfo, *pcbStructInfo);
1069 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1071 DWORD dataLen;
1073 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1075 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1076 DWORD bytesNeeded = sizeof(LPSTR);
1078 if (dataLen)
1080 /* The largest possible string for the first two components
1081 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1083 char firstTwo[6];
1084 const BYTE *ptr;
1086 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1087 pbEncoded[1 + lenBytes] / 40,
1088 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1089 * 40);
1090 bytesNeeded += strlen(firstTwo) + 1;
1091 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1092 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1094 /* large enough for ".4000000" */
1095 char str[9];
1096 int val = 0;
1098 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1099 (*ptr & 0x80))
1101 val <<= 7;
1102 val |= *ptr & 0x7f;
1103 ptr++;
1105 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1106 (*ptr & 0x80))
1108 SetLastError(CRYPT_E_ASN1_CORRUPT);
1109 ret = FALSE;
1111 else
1113 val <<= 7;
1114 val |= *ptr++;
1115 snprintf(str, sizeof(str), ".%d", val);
1116 bytesNeeded += strlen(str);
1120 if (!pvStructInfo)
1121 *pcbStructInfo = bytesNeeded;
1122 else if (*pcbStructInfo < bytesNeeded)
1124 *pcbStructInfo = bytesNeeded;
1125 SetLastError(ERROR_MORE_DATA);
1126 ret = FALSE;
1128 else
1130 if (dataLen)
1132 const BYTE *ptr;
1133 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1135 *pszObjId = 0;
1136 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1137 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1138 40) * 40);
1139 pszObjId += strlen(pszObjId);
1140 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1141 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1143 int val = 0;
1145 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1146 (*ptr & 0x80))
1148 val <<= 7;
1149 val |= *ptr & 0x7f;
1150 ptr++;
1152 val <<= 7;
1153 val |= *ptr++;
1154 sprintf(pszObjId, ".%d", val);
1155 pszObjId += strlen(pszObjId);
1158 else
1159 *(LPSTR *)pvStructInfo = NULL;
1160 *pcbStructInfo = bytesNeeded;
1164 return ret;
1167 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1168 * ahead of time!
1170 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1171 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1172 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1174 struct AsnDecodeSequenceItem items[] = {
1175 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1176 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1177 offsetof(CERT_EXTENSION, pszObjId), 0 },
1178 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1179 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1180 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1181 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1182 offsetof(CERT_EXTENSION, Value.pbData) },
1184 BOOL ret = TRUE;
1185 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1187 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
1188 *pcbStructInfo);
1190 if (ext)
1191 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1192 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1193 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1194 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1195 if (ext)
1196 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1197 debugstr_a(ext->pszObjId));
1198 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1199 return ret;
1202 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1203 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1204 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1206 BOOL ret = TRUE;
1207 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1208 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1209 offsetof(CERT_EXTENSION, pszObjId) };
1210 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1212 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1213 pDecodePara, pvStructInfo, *pcbStructInfo);
1215 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1216 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1217 return ret;
1220 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1221 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1222 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1224 BOOL ret = TRUE;
1226 __TRY
1228 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1229 lpszStructType, pbEncoded, cbEncoded,
1230 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1231 if (ret && pvStructInfo)
1233 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1234 pcbStructInfo, *pcbStructInfo);
1235 if (ret)
1237 CERT_EXTENSIONS *exts;
1239 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1240 pvStructInfo = *(BYTE **)pvStructInfo;
1241 exts = (CERT_EXTENSIONS *)pvStructInfo;
1242 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1243 sizeof(CERT_EXTENSIONS));
1244 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1245 lpszStructType, pbEncoded, cbEncoded,
1246 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1247 pcbStructInfo);
1251 __EXCEPT_PAGE_FAULT
1253 SetLastError(STATUS_ACCESS_VIOLATION);
1254 ret = FALSE;
1256 __ENDTRY
1257 return ret;
1260 /* Warning: this assumes the address of value->Value.pbData is already set, in
1261 * order to avoid overwriting memory. (In some cases, it may change it, if it
1262 * doesn't copy anything to memory.) Be sure to set it correctly!
1264 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1265 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1266 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1268 BOOL ret = TRUE;
1269 DWORD dataLen;
1270 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1272 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1274 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1275 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1277 switch (pbEncoded[0])
1279 case ASN_OCTETSTRING:
1280 valueType = CERT_RDN_OCTET_STRING;
1281 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1282 bytesNeeded += dataLen;
1283 break;
1284 case ASN_NUMERICSTRING:
1285 valueType = CERT_RDN_NUMERIC_STRING;
1286 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1287 bytesNeeded += dataLen;
1288 break;
1289 case ASN_PRINTABLESTRING:
1290 valueType = CERT_RDN_PRINTABLE_STRING;
1291 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1292 bytesNeeded += dataLen;
1293 break;
1294 case ASN_IA5STRING:
1295 valueType = CERT_RDN_IA5_STRING;
1296 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1297 bytesNeeded += dataLen;
1298 break;
1299 case ASN_T61STRING:
1300 valueType = CERT_RDN_T61_STRING;
1301 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1302 bytesNeeded += dataLen;
1303 break;
1304 case ASN_VIDEOTEXSTRING:
1305 valueType = CERT_RDN_VIDEOTEX_STRING;
1306 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1307 bytesNeeded += dataLen;
1308 break;
1309 case ASN_GRAPHICSTRING:
1310 valueType = CERT_RDN_GRAPHIC_STRING;
1311 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1312 bytesNeeded += dataLen;
1313 break;
1314 case ASN_VISIBLESTRING:
1315 valueType = CERT_RDN_VISIBLE_STRING;
1316 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1317 bytesNeeded += dataLen;
1318 break;
1319 case ASN_GENERALSTRING:
1320 valueType = CERT_RDN_GENERAL_STRING;
1321 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1322 bytesNeeded += dataLen;
1323 break;
1324 case ASN_UNIVERSALSTRING:
1325 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1326 SetLastError(CRYPT_E_ASN1_BADTAG);
1327 ret = FALSE;
1328 break;
1329 case ASN_BMPSTRING:
1330 valueType = CERT_RDN_BMP_STRING;
1331 bytesNeeded += dataLen;
1332 break;
1333 case ASN_UTF8STRING:
1334 valueType = CERT_RDN_UTF8_STRING;
1335 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1336 (LPSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1337 break;
1338 default:
1339 SetLastError(CRYPT_E_ASN1_BADTAG);
1340 ret = FALSE;
1342 if (ret)
1344 if (!value)
1345 *pcbStructInfo = bytesNeeded;
1346 else if (*pcbStructInfo < bytesNeeded)
1348 *pcbStructInfo = bytesNeeded;
1349 SetLastError(ERROR_MORE_DATA);
1350 ret = FALSE;
1352 else
1354 *pcbStructInfo = bytesNeeded;
1355 value->dwValueType = valueType;
1356 if (dataLen)
1358 DWORD i;
1360 assert(value->Value.pbData);
1361 switch (pbEncoded[0])
1363 case ASN_OCTETSTRING:
1364 case ASN_NUMERICSTRING:
1365 case ASN_PRINTABLESTRING:
1366 case ASN_IA5STRING:
1367 case ASN_T61STRING:
1368 case ASN_VIDEOTEXSTRING:
1369 case ASN_GRAPHICSTRING:
1370 case ASN_VISIBLESTRING:
1371 case ASN_GENERALSTRING:
1372 value->Value.cbData = dataLen;
1373 if (dataLen)
1375 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1376 memcpy(value->Value.pbData,
1377 pbEncoded + 1 + lenBytes, dataLen);
1378 else
1379 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1380 lenBytes;
1382 break;
1383 case ASN_BMPSTRING:
1385 LPWSTR str = (LPWSTR)value->Value.pbData;
1387 value->Value.cbData = dataLen;
1388 for (i = 0; i < dataLen / 2; i++)
1389 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1390 pbEncoded[1 + lenBytes + 2 * i + 1];
1391 break;
1393 case ASN_UTF8STRING:
1395 LPWSTR str = (LPWSTR)value->Value.pbData;
1397 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1398 (LPSTR)pbEncoded + 1 + lenBytes, dataLen,
1399 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1400 break;
1404 else
1406 value->Value.cbData = 0;
1407 value->Value.pbData = NULL;
1412 return ret;
1415 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1416 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1417 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1419 BOOL ret = TRUE;
1421 __TRY
1423 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1424 lpszStructType, pbEncoded, cbEncoded,
1425 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1426 if (ret && pvStructInfo)
1428 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1429 pcbStructInfo, *pcbStructInfo);
1430 if (ret)
1432 CERT_NAME_VALUE *value;
1434 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1435 pvStructInfo = *(BYTE **)pvStructInfo;
1436 value = (CERT_NAME_VALUE *)pvStructInfo;
1437 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1438 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1439 lpszStructType, pbEncoded, cbEncoded,
1440 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1441 pcbStructInfo);
1445 __EXCEPT_PAGE_FAULT
1447 SetLastError(STATUS_ACCESS_VIOLATION);
1448 ret = FALSE;
1450 __ENDTRY
1451 return ret;
1454 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1455 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1456 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1457 void *pvStructInfo, DWORD *pcbStructInfo)
1459 BOOL ret = TRUE;
1460 DWORD dataLen;
1461 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1463 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1465 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1466 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1468 switch (pbEncoded[0])
1470 case ASN_NUMERICSTRING:
1471 valueType = CERT_RDN_NUMERIC_STRING;
1472 bytesNeeded += dataLen * 2;
1473 break;
1474 case ASN_PRINTABLESTRING:
1475 valueType = CERT_RDN_PRINTABLE_STRING;
1476 bytesNeeded += dataLen * 2;
1477 break;
1478 case ASN_IA5STRING:
1479 valueType = CERT_RDN_IA5_STRING;
1480 bytesNeeded += dataLen * 2;
1481 break;
1482 case ASN_T61STRING:
1483 valueType = CERT_RDN_T61_STRING;
1484 bytesNeeded += dataLen * 2;
1485 break;
1486 case ASN_VIDEOTEXSTRING:
1487 valueType = CERT_RDN_VIDEOTEX_STRING;
1488 bytesNeeded += dataLen * 2;
1489 break;
1490 case ASN_GRAPHICSTRING:
1491 valueType = CERT_RDN_GRAPHIC_STRING;
1492 bytesNeeded += dataLen * 2;
1493 break;
1494 case ASN_VISIBLESTRING:
1495 valueType = CERT_RDN_VISIBLE_STRING;
1496 bytesNeeded += dataLen * 2;
1497 break;
1498 case ASN_GENERALSTRING:
1499 valueType = CERT_RDN_GENERAL_STRING;
1500 bytesNeeded += dataLen * 2;
1501 break;
1502 case ASN_UNIVERSALSTRING:
1503 valueType = CERT_RDN_UNIVERSAL_STRING;
1504 bytesNeeded += dataLen / 2;
1505 break;
1506 case ASN_BMPSTRING:
1507 valueType = CERT_RDN_BMP_STRING;
1508 bytesNeeded += dataLen;
1509 break;
1510 case ASN_UTF8STRING:
1511 valueType = CERT_RDN_UTF8_STRING;
1512 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1513 (LPSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1514 break;
1515 default:
1516 SetLastError(CRYPT_E_ASN1_BADTAG);
1517 ret = FALSE;
1519 if (ret)
1521 if (!value)
1522 *pcbStructInfo = bytesNeeded;
1523 else if (*pcbStructInfo < bytesNeeded)
1525 *pcbStructInfo = bytesNeeded;
1526 SetLastError(ERROR_MORE_DATA);
1527 ret = FALSE;
1529 else
1531 *pcbStructInfo = bytesNeeded;
1532 value->dwValueType = valueType;
1533 if (dataLen)
1535 DWORD i;
1536 LPWSTR str = (LPWSTR)value->Value.pbData;
1538 assert(value->Value.pbData);
1539 switch (pbEncoded[0])
1541 case ASN_NUMERICSTRING:
1542 case ASN_PRINTABLESTRING:
1543 case ASN_IA5STRING:
1544 case ASN_T61STRING:
1545 case ASN_VIDEOTEXSTRING:
1546 case ASN_GRAPHICSTRING:
1547 case ASN_VISIBLESTRING:
1548 case ASN_GENERALSTRING:
1549 value->Value.cbData = dataLen * 2;
1550 for (i = 0; i < dataLen; i++)
1551 str[i] = pbEncoded[1 + lenBytes + i];
1552 break;
1553 case ASN_UNIVERSALSTRING:
1554 value->Value.cbData = dataLen / 2;
1555 for (i = 0; i < dataLen / 4; i++)
1556 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1557 | pbEncoded[1 + lenBytes + 2 * i + 3];
1558 break;
1559 case ASN_BMPSTRING:
1560 value->Value.cbData = dataLen;
1561 for (i = 0; i < dataLen / 2; i++)
1562 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1563 pbEncoded[1 + lenBytes + 2 * i + 1];
1564 break;
1565 case ASN_UTF8STRING:
1566 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1567 (LPSTR)pbEncoded + 1 + lenBytes, dataLen,
1568 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1569 break;
1572 else
1574 value->Value.cbData = 0;
1575 value->Value.pbData = NULL;
1580 return ret;
1583 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1584 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1585 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1587 BOOL ret = TRUE;
1589 __TRY
1591 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1592 lpszStructType, pbEncoded, cbEncoded,
1593 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1594 if (ret && pvStructInfo)
1596 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1597 pcbStructInfo, *pcbStructInfo);
1598 if (ret)
1600 CERT_NAME_VALUE *value;
1602 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1603 pvStructInfo = *(BYTE **)pvStructInfo;
1604 value = (CERT_NAME_VALUE *)pvStructInfo;
1605 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1606 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1607 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1608 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1609 pcbStructInfo);
1613 __EXCEPT_PAGE_FAULT
1615 SetLastError(STATUS_ACCESS_VIOLATION);
1616 ret = FALSE;
1618 __ENDTRY
1619 return ret;
1622 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1623 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1624 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1626 BOOL ret;
1627 struct AsnDecodeSequenceItem items[] = {
1628 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1629 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1630 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1631 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1632 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1633 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1635 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1637 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1638 pvStructInfo, *pcbStructInfo);
1640 if (attr)
1641 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1642 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1643 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1644 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1645 if (attr)
1647 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1648 debugstr_a(attr->pszObjId));
1649 TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1651 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1652 return ret;
1655 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1656 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1657 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1659 BOOL ret = TRUE;
1660 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1661 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1662 offsetof(CERT_RDN_ATTR, pszObjId) };
1663 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1665 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1666 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1667 return ret;
1670 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1671 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1672 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1674 BOOL ret = TRUE;
1676 __TRY
1678 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1679 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1680 offsetof(CERT_RDN, rgRDNAttr) };
1682 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1683 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1685 __EXCEPT_PAGE_FAULT
1687 SetLastError(STATUS_ACCESS_VIOLATION);
1688 ret = FALSE;
1690 __ENDTRY
1691 return ret;
1694 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
1695 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1696 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1698 BOOL ret;
1699 struct AsnDecodeSequenceItem items[] = {
1700 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1701 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1702 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1703 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1704 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1705 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1707 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1709 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1710 pvStructInfo, *pcbStructInfo);
1712 if (attr)
1713 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1714 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1715 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1716 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1717 if (attr)
1719 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1720 debugstr_a(attr->pszObjId));
1721 TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1723 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1724 return ret;
1727 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
1728 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1729 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1731 BOOL ret = TRUE;
1732 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1733 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1734 offsetof(CERT_RDN_ATTR, pszObjId) };
1735 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1737 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1738 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1739 return ret;
1742 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1743 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1744 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1746 BOOL ret = TRUE;
1748 __TRY
1750 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1751 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1752 offsetof(CERT_RDN, rgRDNAttr) };
1754 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1755 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1757 __EXCEPT_PAGE_FAULT
1759 SetLastError(STATUS_ACCESS_VIOLATION);
1760 ret = FALSE;
1762 __ENDTRY
1763 return ret;
1766 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(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;
1771 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1773 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1774 pDecodePara, pvStructInfo, *pcbStructInfo);
1776 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1777 bytesNeeded += cbEncoded;
1778 if (!pvStructInfo)
1779 *pcbStructInfo = bytesNeeded;
1780 else if (*pcbStructInfo < bytesNeeded)
1782 SetLastError(ERROR_MORE_DATA);
1783 *pcbStructInfo = bytesNeeded;
1784 ret = FALSE;
1786 else
1788 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1790 *pcbStructInfo = bytesNeeded;
1791 blob->cbData = cbEncoded;
1792 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1793 blob->pbData = (LPBYTE)pbEncoded;
1794 else
1796 assert(blob->pbData);
1797 memcpy(blob->pbData, pbEncoded, blob->cbData);
1800 return ret;
1803 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1804 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1805 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1807 CRYPT_ALGORITHM_IDENTIFIER *algo =
1808 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1809 BOOL ret = TRUE;
1810 struct AsnDecodeSequenceItem items[] = {
1811 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1812 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1813 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1814 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1815 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1816 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1819 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1820 pDecodePara, pvStructInfo, *pcbStructInfo);
1822 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1823 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1824 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1825 if (ret && pvStructInfo)
1827 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1828 debugstr_a(algo->pszObjId));
1830 return ret;
1833 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1834 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1835 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1837 BOOL ret = TRUE;
1838 struct AsnDecodeSequenceItem items[] = {
1839 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1840 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1841 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1842 Algorithm.pszObjId) },
1843 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1844 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1845 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1847 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1849 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1850 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1851 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1852 info->Algorithm.Parameters.pbData : NULL);
1853 return ret;
1856 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1857 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1858 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1860 BOOL ret = TRUE;
1862 __TRY
1864 DWORD bytesNeeded;
1866 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1867 lpszStructType, pbEncoded, cbEncoded,
1868 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1870 if (!pvStructInfo)
1871 *pcbStructInfo = bytesNeeded;
1872 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1873 pvStructInfo, pcbStructInfo, bytesNeeded)))
1875 PCERT_PUBLIC_KEY_INFO info;
1877 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1878 pvStructInfo = *(BYTE **)pvStructInfo;
1879 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1880 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
1881 sizeof(CERT_PUBLIC_KEY_INFO);
1882 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1883 lpszStructType, pbEncoded, cbEncoded,
1884 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1885 &bytesNeeded);
1889 __EXCEPT_PAGE_FAULT
1891 SetLastError(STATUS_ACCESS_VIOLATION);
1892 ret = FALSE;
1894 __ENDTRY
1895 return ret;
1898 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
1899 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1900 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1902 BOOL ret;
1904 if (cbEncoded < 3)
1906 SetLastError(CRYPT_E_ASN1_CORRUPT);
1907 return FALSE;
1909 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
1911 SetLastError(CRYPT_E_ASN1_CORRUPT);
1912 return FALSE;
1914 if (pbEncoded[1] > 1)
1916 SetLastError(CRYPT_E_ASN1_CORRUPT);
1917 return FALSE;
1919 if (!pvStructInfo)
1921 *pcbStructInfo = sizeof(BOOL);
1922 ret = TRUE;
1924 else if (*pcbStructInfo < sizeof(BOOL))
1926 *pcbStructInfo = sizeof(BOOL);
1927 SetLastError(ERROR_MORE_DATA);
1928 ret = FALSE;
1930 else
1932 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
1933 ret = TRUE;
1935 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1936 return ret;
1939 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
1940 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1941 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1943 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
1944 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
1945 BOOL ret;
1947 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1948 pDecodePara, pvStructInfo, *pcbStructInfo);
1950 if (cbEncoded < 2)
1952 SetLastError(CRYPT_E_ASN1_CORRUPT);
1953 return FALSE;
1955 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
1957 SetLastError(CRYPT_E_ASN1_BADTAG);
1958 return FALSE;
1960 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1961 if (1 + lenBytes > cbEncoded)
1963 SetLastError(CRYPT_E_ASN1_CORRUPT);
1964 return FALSE;
1966 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1968 switch (pbEncoded[0] & ASN_TYPE_MASK)
1970 case 1: /* rfc822Name */
1971 case 2: /* dNSName */
1972 case 6: /* uniformResourceIdentifier */
1973 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1974 break;
1975 case 7: /* iPAddress */
1976 bytesNeeded += dataLen;
1977 break;
1978 case 8: /* registeredID */
1979 /* FIXME: decode as OID */
1980 case 0: /* otherName */
1981 case 4: /* directoryName */
1982 FIXME("stub\n");
1983 SetLastError(CRYPT_E_ASN1_BADTAG);
1984 ret = FALSE;
1985 break;
1986 case 3: /* x400Address, unimplemented */
1987 case 5: /* ediPartyName, unimplemented */
1988 SetLastError(CRYPT_E_ASN1_BADTAG);
1989 ret = FALSE;
1990 break;
1991 default:
1992 SetLastError(CRYPT_E_ASN1_CORRUPT);
1993 ret = FALSE;
1995 if (ret)
1997 if (!entry)
1998 *pcbStructInfo = bytesNeeded;
1999 else if (*pcbStructInfo < bytesNeeded)
2001 *pcbStructInfo = bytesNeeded;
2002 SetLastError(ERROR_MORE_DATA);
2003 ret = FALSE;
2005 else
2007 *pcbStructInfo = bytesNeeded;
2008 /* MS used values one greater than the asn1 ones.. sigh */
2009 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2010 switch (pbEncoded[0] & ASN_TYPE_MASK)
2012 case 1: /* rfc822Name */
2013 case 2: /* dNSName */
2014 case 6: /* uniformResourceIdentifier */
2016 DWORD i;
2018 for (i = 0; i < dataLen; i++)
2019 entry->u.pwszURL[i] =
2020 (WCHAR)pbEncoded[1 + lenBytes + i];
2021 entry->u.pwszURL[i] = 0;
2022 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2023 debugstr_w(entry->u.pwszURL));
2024 break;
2026 case 7: /* iPAddress */
2027 /* The next data pointer is in the pwszURL spot, that is,
2028 * the first 4 bytes. Need to move it to the next spot.
2030 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2031 entry->u.IPAddress.cbData = dataLen;
2032 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2033 dataLen);
2034 break;
2039 return ret;
2042 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2043 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2044 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2046 BOOL ret = TRUE;
2047 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2048 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2049 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2050 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2052 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2053 pDecodePara, pvStructInfo, *pcbStructInfo);
2055 if (info)
2056 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2057 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2058 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2059 return ret;
2062 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2063 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2064 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2066 BOOL ret = TRUE;
2068 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2069 pDecodePara, pvStructInfo, *pcbStructInfo);
2071 __TRY
2073 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2074 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2075 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2077 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2078 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2080 __EXCEPT_PAGE_FAULT
2082 SetLastError(STATUS_ACCESS_VIOLATION);
2083 ret = FALSE;
2085 __ENDTRY
2086 return ret;
2089 struct PATH_LEN_CONSTRAINT
2091 BOOL fPathLenConstraint;
2092 DWORD dwPathLenConstraint;
2095 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2096 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2097 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2099 BOOL ret = TRUE;
2101 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2102 pvStructInfo, *pcbStructInfo);
2104 if (cbEncoded)
2106 if (pbEncoded[0] == ASN_INTEGER)
2108 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2110 if (!pvStructInfo)
2111 *pcbStructInfo = bytesNeeded;
2112 else if (*pcbStructInfo < bytesNeeded)
2114 SetLastError(ERROR_MORE_DATA);
2115 *pcbStructInfo = bytesNeeded;
2116 ret = FALSE;
2118 else
2120 struct PATH_LEN_CONSTRAINT *constraint =
2121 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2122 DWORD size = sizeof(constraint->dwPathLenConstraint);
2124 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2125 pbEncoded, cbEncoded, 0, NULL,
2126 &constraint->dwPathLenConstraint, &size);
2127 if (ret)
2128 constraint->fPathLenConstraint = TRUE;
2129 TRACE("got an int, dwPathLenConstraint is %ld\n",
2130 constraint->dwPathLenConstraint);
2133 else
2135 SetLastError(CRYPT_E_ASN1_CORRUPT);
2136 ret = FALSE;
2139 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2140 return ret;
2143 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2144 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2145 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2147 BOOL ret;
2148 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2149 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2150 offsetof(CERT_NAME_BLOB, pbData) };
2151 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2153 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2154 pDecodePara, pvStructInfo, *pcbStructInfo);
2156 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2157 pDecodePara, pvStructInfo, pcbStructInfo,
2158 entries ? entries->rgItems : NULL);
2159 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
2160 return ret;
2163 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2164 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2165 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2167 BOOL ret;
2169 __TRY
2171 struct AsnDecodeSequenceItem items[] = {
2172 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2173 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2174 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2175 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2176 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2177 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2178 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2179 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2180 sizeof(struct GenericArray), TRUE, TRUE,
2181 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2184 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2185 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2186 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2188 __EXCEPT_PAGE_FAULT
2190 SetLastError(STATUS_ACCESS_VIOLATION);
2191 ret = FALSE;
2193 __ENDTRY
2194 return ret;
2197 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2198 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2199 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2201 BOOL ret;
2203 __TRY
2205 struct AsnDecodeSequenceItem items[] = {
2206 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2207 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2208 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2209 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2210 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2213 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2214 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2215 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2217 __EXCEPT_PAGE_FAULT
2219 SetLastError(STATUS_ACCESS_VIOLATION);
2220 ret = FALSE;
2222 __ENDTRY
2223 return ret;
2226 #define RSA1_MAGIC 0x31415352
2228 struct DECODED_RSA_PUB_KEY
2230 DWORD pubexp;
2231 CRYPT_INTEGER_BLOB modulus;
2234 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2235 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2236 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2238 BOOL ret;
2240 __TRY
2242 struct AsnDecodeSequenceItem items[] = {
2243 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2244 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2245 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2246 0 },
2247 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2248 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2250 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2251 DWORD size = 0;
2253 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2254 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2255 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2256 if (ret)
2258 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2259 decodedKey->modulus.cbData;
2261 if (!pvStructInfo)
2263 *pcbStructInfo = bytesNeeded;
2264 ret = TRUE;
2266 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2267 pvStructInfo, pcbStructInfo, bytesNeeded)))
2269 BLOBHEADER *hdr;
2270 RSAPUBKEY *rsaPubKey;
2272 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2273 pvStructInfo = *(BYTE **)pvStructInfo;
2274 hdr = (BLOBHEADER *)pvStructInfo;
2275 hdr->bType = PUBLICKEYBLOB;
2276 hdr->bVersion = CUR_BLOB_VERSION;
2277 hdr->reserved = 0;
2278 hdr->aiKeyAlg = CALG_RSA_KEYX;
2279 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2280 sizeof(BLOBHEADER));
2281 rsaPubKey->magic = RSA1_MAGIC;
2282 rsaPubKey->pubexp = decodedKey->pubexp;
2283 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2284 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2285 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2286 decodedKey->modulus.cbData);
2288 LocalFree(decodedKey);
2291 __EXCEPT_PAGE_FAULT
2293 SetLastError(STATUS_ACCESS_VIOLATION);
2294 ret = FALSE;
2296 __ENDTRY
2297 return ret;
2300 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2301 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2302 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2304 BOOL ret;
2305 DWORD bytesNeeded, dataLen;
2307 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2308 pDecodePara, pvStructInfo, *pcbStructInfo);
2310 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2312 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2313 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2314 else
2315 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2316 if (!pvStructInfo)
2317 *pcbStructInfo = bytesNeeded;
2318 else if (*pcbStructInfo < bytesNeeded)
2320 SetLastError(ERROR_MORE_DATA);
2321 *pcbStructInfo = bytesNeeded;
2322 ret = FALSE;
2324 else
2326 CRYPT_DATA_BLOB *blob;
2327 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2329 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2330 blob->cbData = dataLen;
2331 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2332 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2333 else
2335 assert(blob->pbData);
2336 if (blob->cbData)
2337 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2338 blob->cbData);
2342 return ret;
2345 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2346 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2347 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2349 BOOL ret;
2351 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2352 pDecodePara, pvStructInfo, *pcbStructInfo);
2354 __TRY
2356 DWORD bytesNeeded;
2358 if (!cbEncoded)
2360 SetLastError(CRYPT_E_ASN1_CORRUPT);
2361 ret = FALSE;
2363 else if (pbEncoded[0] != ASN_OCTETSTRING)
2365 SetLastError(CRYPT_E_ASN1_BADTAG);
2366 ret = FALSE;
2368 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2369 lpszStructType, pbEncoded, cbEncoded,
2370 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2372 if (!pvStructInfo)
2373 *pcbStructInfo = bytesNeeded;
2374 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2375 pvStructInfo, pcbStructInfo, bytesNeeded)))
2377 CRYPT_DATA_BLOB *blob;
2379 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2380 pvStructInfo = *(BYTE **)pvStructInfo;
2381 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2382 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2383 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2384 lpszStructType, pbEncoded, cbEncoded,
2385 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2386 &bytesNeeded);
2390 __EXCEPT_PAGE_FAULT
2392 SetLastError(STATUS_ACCESS_VIOLATION);
2393 ret = FALSE;
2395 __ENDTRY
2396 return ret;
2399 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2400 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2401 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2403 BOOL ret;
2405 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2406 pDecodePara, pvStructInfo, *pcbStructInfo);
2408 if (pbEncoded[0] == ASN_BITSTRING)
2410 DWORD bytesNeeded, dataLen;
2412 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2414 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2415 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2416 else
2417 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2418 if (!pvStructInfo)
2419 *pcbStructInfo = bytesNeeded;
2420 else if (*pcbStructInfo < bytesNeeded)
2422 *pcbStructInfo = bytesNeeded;
2423 SetLastError(ERROR_MORE_DATA);
2424 ret = FALSE;
2426 else
2428 CRYPT_BIT_BLOB *blob;
2430 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2431 blob->cbData = dataLen - 1;
2432 blob->cUnusedBits = *(pbEncoded + 1 +
2433 GET_LEN_BYTES(pbEncoded[1]));
2434 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2436 blob->pbData = (BYTE *)pbEncoded + 2 +
2437 GET_LEN_BYTES(pbEncoded[1]);
2439 else
2441 assert(blob->pbData);
2442 if (blob->cbData)
2444 BYTE mask = 0xff << blob->cUnusedBits;
2446 memcpy(blob->pbData, pbEncoded + 2 +
2447 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2448 blob->pbData[blob->cbData - 1] &= mask;
2454 else
2456 SetLastError(CRYPT_E_ASN1_BADTAG);
2457 ret = FALSE;
2459 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2460 return ret;
2463 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2464 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2465 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2467 BOOL ret;
2469 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2470 pDecodePara, pvStructInfo, pcbStructInfo);
2472 __TRY
2474 DWORD bytesNeeded;
2476 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2477 lpszStructType, pbEncoded, cbEncoded,
2478 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2480 if (!pvStructInfo)
2481 *pcbStructInfo = bytesNeeded;
2482 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2483 pvStructInfo, pcbStructInfo, bytesNeeded)))
2485 CRYPT_BIT_BLOB *blob;
2487 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2488 pvStructInfo = *(BYTE **)pvStructInfo;
2489 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2490 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2491 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2492 lpszStructType, pbEncoded, cbEncoded,
2493 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2494 &bytesNeeded);
2498 __EXCEPT_PAGE_FAULT
2500 SetLastError(STATUS_ACCESS_VIOLATION);
2501 ret = FALSE;
2503 __ENDTRY
2504 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2505 return ret;
2508 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2509 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2510 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2512 BOOL ret;
2514 if (!pvStructInfo)
2516 *pcbStructInfo = sizeof(int);
2517 return TRUE;
2519 __TRY
2521 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2522 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2523 DWORD size = sizeof(buf);
2525 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2526 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2527 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size);
2528 if (ret)
2530 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2531 pvStructInfo, pcbStructInfo, sizeof(int))))
2533 int val, i;
2535 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2536 pvStructInfo = *(BYTE **)pvStructInfo;
2537 if (blob->pbData[blob->cbData - 1] & 0x80)
2539 /* initialize to a negative value to sign-extend */
2540 val = -1;
2542 else
2543 val = 0;
2544 for (i = 0; i < blob->cbData; i++)
2546 val <<= 8;
2547 val |= blob->pbData[blob->cbData - i - 1];
2549 memcpy(pvStructInfo, &val, sizeof(int));
2552 else if (GetLastError() == ERROR_MORE_DATA)
2553 SetLastError(CRYPT_E_ASN1_LARGE);
2555 __EXCEPT_PAGE_FAULT
2557 SetLastError(STATUS_ACCESS_VIOLATION);
2558 ret = FALSE;
2560 __ENDTRY
2561 return ret;
2564 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2565 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2566 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2568 BOOL ret;
2570 if (pbEncoded[0] == ASN_INTEGER)
2572 DWORD bytesNeeded, dataLen;
2574 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2576 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2578 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2579 if (!pvStructInfo)
2580 *pcbStructInfo = bytesNeeded;
2581 else if (*pcbStructInfo < bytesNeeded)
2583 *pcbStructInfo = bytesNeeded;
2584 SetLastError(ERROR_MORE_DATA);
2585 ret = FALSE;
2587 else
2589 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2591 blob->cbData = dataLen;
2592 assert(blob->pbData);
2593 if (blob->cbData)
2595 DWORD i;
2597 for (i = 0; i < blob->cbData; i++)
2599 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2600 dataLen - i - 1);
2606 else
2608 SetLastError(CRYPT_E_ASN1_BADTAG);
2609 ret = FALSE;
2611 return ret;
2614 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2615 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2616 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2618 BOOL ret;
2620 __TRY
2622 DWORD bytesNeeded;
2624 if ((ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2625 lpszStructType, pbEncoded, cbEncoded,
2626 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2628 if (!pvStructInfo)
2629 *pcbStructInfo = bytesNeeded;
2630 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2631 pvStructInfo, pcbStructInfo, bytesNeeded)))
2633 CRYPT_INTEGER_BLOB *blob;
2635 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2636 pvStructInfo = *(BYTE **)pvStructInfo;
2637 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2638 blob->pbData = (BYTE *)pvStructInfo +
2639 sizeof(CRYPT_INTEGER_BLOB);
2640 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2641 lpszStructType, pbEncoded, cbEncoded,
2642 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2643 &bytesNeeded);
2647 __EXCEPT_PAGE_FAULT
2649 SetLastError(STATUS_ACCESS_VIOLATION);
2650 ret = FALSE;
2652 __ENDTRY
2653 return ret;
2656 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
2657 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2658 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2659 void *pvStructInfo, DWORD *pcbStructInfo)
2661 BOOL ret;
2663 if (pbEncoded[0] == ASN_INTEGER)
2665 DWORD bytesNeeded, dataLen;
2667 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2669 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2671 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2672 if (!pvStructInfo)
2673 *pcbStructInfo = bytesNeeded;
2674 else if (*pcbStructInfo < bytesNeeded)
2676 *pcbStructInfo = bytesNeeded;
2677 SetLastError(ERROR_MORE_DATA);
2678 ret = FALSE;
2680 else
2682 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2684 blob->cbData = dataLen;
2685 assert(blob->pbData);
2686 /* remove leading zero byte if it exists */
2687 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2689 blob->cbData--;
2690 blob->pbData++;
2692 if (blob->cbData)
2694 DWORD i;
2696 for (i = 0; i < blob->cbData; i++)
2698 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2699 dataLen - i - 1);
2705 else
2707 SetLastError(CRYPT_E_ASN1_BADTAG);
2708 ret = FALSE;
2710 return ret;
2713 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2714 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2715 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2717 BOOL ret;
2719 __TRY
2721 DWORD bytesNeeded;
2723 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2724 lpszStructType, pbEncoded, cbEncoded,
2725 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2727 if (!pvStructInfo)
2728 *pcbStructInfo = bytesNeeded;
2729 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2730 pvStructInfo, pcbStructInfo, bytesNeeded)))
2732 CRYPT_INTEGER_BLOB *blob;
2734 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2735 pvStructInfo = *(BYTE **)pvStructInfo;
2736 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2737 blob->pbData = (BYTE *)pvStructInfo +
2738 sizeof(CRYPT_INTEGER_BLOB);
2739 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2740 lpszStructType, pbEncoded, cbEncoded,
2741 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2742 &bytesNeeded);
2746 __EXCEPT_PAGE_FAULT
2748 SetLastError(STATUS_ACCESS_VIOLATION);
2749 ret = FALSE;
2751 __ENDTRY
2752 return ret;
2755 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
2756 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2757 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2759 BOOL ret;
2761 if (!pvStructInfo)
2763 *pcbStructInfo = sizeof(int);
2764 return TRUE;
2766 __TRY
2768 if (pbEncoded[0] == ASN_ENUMERATED)
2770 unsigned int val = 0, i;
2772 if (cbEncoded <= 1)
2774 SetLastError(CRYPT_E_ASN1_EOD);
2775 ret = FALSE;
2777 else if (pbEncoded[1] == 0)
2779 SetLastError(CRYPT_E_ASN1_CORRUPT);
2780 ret = FALSE;
2782 else
2784 /* A little strange looking, but we have to accept a sign byte:
2785 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
2786 * assuming a small length is okay here, it has to be in short
2787 * form.
2789 if (pbEncoded[1] > sizeof(unsigned int) + 1)
2791 SetLastError(CRYPT_E_ASN1_LARGE);
2792 return FALSE;
2794 for (i = 0; i < pbEncoded[1]; i++)
2796 val <<= 8;
2797 val |= pbEncoded[2 + i];
2799 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2800 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
2802 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2803 pvStructInfo = *(BYTE **)pvStructInfo;
2804 memcpy(pvStructInfo, &val, sizeof(unsigned int));
2808 else
2810 SetLastError(CRYPT_E_ASN1_BADTAG);
2811 ret = FALSE;
2814 __EXCEPT_PAGE_FAULT
2816 SetLastError(STATUS_ACCESS_VIOLATION);
2817 ret = FALSE;
2819 __ENDTRY
2820 return ret;
2823 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
2824 * if it fails.
2826 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
2827 do { \
2828 BYTE i; \
2830 (word) = 0; \
2831 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
2833 if (!isdigit(*(pbEncoded))) \
2835 SetLastError(CRYPT_E_ASN1_CORRUPT); \
2836 ret = FALSE; \
2838 else \
2840 (word) *= 10; \
2841 (word) += *(pbEncoded)++ - '0'; \
2844 } while (0)
2846 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
2847 SYSTEMTIME *sysTime)
2849 BOOL ret;
2851 __TRY
2853 ret = TRUE;
2854 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
2856 WORD hours, minutes = 0;
2857 BYTE sign = *pbEncoded++;
2859 len--;
2860 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
2861 if (ret && hours >= 24)
2863 SetLastError(CRYPT_E_ASN1_CORRUPT);
2864 ret = FALSE;
2866 else if (len >= 2)
2868 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
2869 if (ret && minutes >= 60)
2871 SetLastError(CRYPT_E_ASN1_CORRUPT);
2872 ret = FALSE;
2875 if (ret)
2877 if (sign == '+')
2879 sysTime->wHour += hours;
2880 sysTime->wMinute += minutes;
2882 else
2884 if (hours > sysTime->wHour)
2886 sysTime->wDay--;
2887 sysTime->wHour = 24 - (hours - sysTime->wHour);
2889 else
2890 sysTime->wHour -= hours;
2891 if (minutes > sysTime->wMinute)
2893 sysTime->wHour--;
2894 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
2896 else
2897 sysTime->wMinute -= minutes;
2902 __EXCEPT_PAGE_FAULT
2904 SetLastError(STATUS_ACCESS_VIOLATION);
2905 ret = FALSE;
2907 __ENDTRY
2908 return ret;
2911 #define MIN_ENCODED_TIME_LENGTH 10
2913 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
2914 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2915 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2917 BOOL ret;
2919 if (!pvStructInfo)
2921 *pcbStructInfo = sizeof(FILETIME);
2922 return TRUE;
2924 __TRY
2926 ret = TRUE;
2927 if (pbEncoded[0] == ASN_UTCTIME)
2929 if (cbEncoded <= 1)
2931 SetLastError(CRYPT_E_ASN1_EOD);
2932 ret = FALSE;
2934 else if (pbEncoded[1] > 0x7f)
2936 /* long-form date strings really can't be valid */
2937 SetLastError(CRYPT_E_ASN1_CORRUPT);
2938 ret = FALSE;
2940 else
2942 SYSTEMTIME sysTime = { 0 };
2943 BYTE len = pbEncoded[1];
2945 if (len < MIN_ENCODED_TIME_LENGTH)
2947 SetLastError(CRYPT_E_ASN1_CORRUPT);
2948 ret = FALSE;
2950 else
2952 pbEncoded += 2;
2953 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
2954 if (sysTime.wYear >= 50)
2955 sysTime.wYear += 1900;
2956 else
2957 sysTime.wYear += 2000;
2958 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2959 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2960 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2961 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
2962 if (ret && len > 0)
2964 if (len >= 2 && isdigit(*pbEncoded) &&
2965 isdigit(*(pbEncoded + 1)))
2966 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2967 sysTime.wSecond);
2968 else if (isdigit(*pbEncoded))
2969 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
2970 sysTime.wSecond);
2971 if (ret)
2972 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2973 &sysTime);
2975 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2976 pDecodePara, pvStructInfo, pcbStructInfo,
2977 sizeof(FILETIME))))
2979 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2980 pvStructInfo = *(BYTE **)pvStructInfo;
2981 ret = SystemTimeToFileTime(&sysTime,
2982 (FILETIME *)pvStructInfo);
2987 else
2989 SetLastError(CRYPT_E_ASN1_BADTAG);
2990 ret = FALSE;
2993 __EXCEPT_PAGE_FAULT
2995 SetLastError(STATUS_ACCESS_VIOLATION);
2996 ret = FALSE;
2998 __ENDTRY
2999 return ret;
3002 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3003 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3004 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3006 BOOL ret;
3008 if (!pvStructInfo)
3010 *pcbStructInfo = sizeof(FILETIME);
3011 return TRUE;
3013 __TRY
3015 ret = TRUE;
3016 if (pbEncoded[0] == ASN_GENERALTIME)
3018 if (cbEncoded <= 1)
3020 SetLastError(CRYPT_E_ASN1_EOD);
3021 ret = FALSE;
3023 else if (pbEncoded[1] > 0x7f)
3025 /* long-form date strings really can't be valid */
3026 SetLastError(CRYPT_E_ASN1_CORRUPT);
3027 ret = FALSE;
3029 else
3031 BYTE len = pbEncoded[1];
3033 if (len < MIN_ENCODED_TIME_LENGTH)
3035 SetLastError(CRYPT_E_ASN1_CORRUPT);
3036 ret = FALSE;
3038 else
3040 SYSTEMTIME sysTime = { 0 };
3042 pbEncoded += 2;
3043 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3044 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3045 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3046 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3047 if (ret && len > 0)
3049 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3050 sysTime.wMinute);
3051 if (ret && len > 0)
3052 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3053 sysTime.wSecond);
3054 if (ret && len > 0 && (*pbEncoded == '.' ||
3055 *pbEncoded == ','))
3057 BYTE digits;
3059 pbEncoded++;
3060 len--;
3061 /* workaround macro weirdness */
3062 digits = min(len, 3);
3063 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3064 sysTime.wMilliseconds);
3066 if (ret)
3067 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3068 &sysTime);
3070 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3071 pDecodePara, pvStructInfo, pcbStructInfo,
3072 sizeof(FILETIME))))
3074 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3075 pvStructInfo = *(BYTE **)pvStructInfo;
3076 ret = SystemTimeToFileTime(&sysTime,
3077 (FILETIME *)pvStructInfo);
3082 else
3084 SetLastError(CRYPT_E_ASN1_BADTAG);
3085 ret = FALSE;
3088 __EXCEPT_PAGE_FAULT
3090 SetLastError(STATUS_ACCESS_VIOLATION);
3091 ret = FALSE;
3093 __ENDTRY
3094 return ret;
3097 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3098 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3099 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3101 BOOL ret;
3103 __TRY
3105 if (pbEncoded[0] == ASN_UTCTIME)
3106 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3107 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3108 pcbStructInfo);
3109 else if (pbEncoded[0] == ASN_GENERALTIME)
3110 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3111 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3112 pvStructInfo, pcbStructInfo);
3113 else
3115 SetLastError(CRYPT_E_ASN1_BADTAG);
3116 ret = FALSE;
3119 __EXCEPT_PAGE_FAULT
3121 SetLastError(STATUS_ACCESS_VIOLATION);
3122 ret = FALSE;
3124 __ENDTRY
3125 return ret;
3128 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3129 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3130 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3132 BOOL ret = TRUE;
3134 __TRY
3136 if (pbEncoded[0] == ASN_SEQUENCEOF)
3138 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3140 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3142 BYTE lenBytes;
3143 const BYTE *ptr;
3145 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3146 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3147 cValue = 0;
3148 ptr = pbEncoded + 1 + lenBytes;
3149 remainingLen = dataLen;
3150 while (ret && remainingLen)
3152 DWORD nextLen;
3154 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3155 if (ret)
3157 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3159 remainingLen -= 1 + nextLenBytes + nextLen;
3160 ptr += 1 + nextLenBytes + nextLen;
3161 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3162 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3163 bytesNeeded += 1 + nextLenBytes + nextLen;
3164 cValue++;
3167 if (ret)
3169 CRYPT_SEQUENCE_OF_ANY *seq;
3170 BYTE *nextPtr;
3171 DWORD i;
3173 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3174 pvStructInfo, pcbStructInfo, bytesNeeded)))
3176 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3177 pvStructInfo = *(BYTE **)pvStructInfo;
3178 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3179 seq->cValue = cValue;
3180 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3181 sizeof(*seq));
3182 nextPtr = (BYTE *)seq->rgValue +
3183 cValue * sizeof(CRYPT_DER_BLOB);
3184 ptr = pbEncoded + 1 + lenBytes;
3185 remainingLen = dataLen;
3186 i = 0;
3187 while (ret && remainingLen)
3189 DWORD nextLen;
3191 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3192 if (ret)
3194 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3196 seq->rgValue[i].cbData = 1 + nextLenBytes +
3197 nextLen;
3198 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3199 seq->rgValue[i].pbData = (BYTE *)ptr;
3200 else
3202 seq->rgValue[i].pbData = nextPtr;
3203 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3204 nextLen);
3205 nextPtr += 1 + nextLenBytes + nextLen;
3207 remainingLen -= 1 + nextLenBytes + nextLen;
3208 ptr += 1 + nextLenBytes + nextLen;
3209 i++;
3216 else
3218 SetLastError(CRYPT_E_ASN1_BADTAG);
3219 ret = FALSE;
3222 __EXCEPT_PAGE_FAULT
3224 SetLastError(STATUS_ACCESS_VIOLATION);
3225 ret = FALSE;
3227 __ENDTRY
3228 return ret;
3231 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3232 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3233 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3235 BOOL ret;
3237 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3239 DWORD bytesNeeded, dataLen;
3241 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3243 struct AsnArrayDescriptor arrayDesc = {
3244 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3245 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3246 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3247 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3249 if (dataLen)
3251 DWORD nameLen;
3253 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3254 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3255 0, NULL, NULL, &nameLen, NULL);
3256 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3258 else
3259 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3260 if (!pvStructInfo)
3261 *pcbStructInfo = bytesNeeded;
3262 else if (*pcbStructInfo < bytesNeeded)
3264 *pcbStructInfo = bytesNeeded;
3265 SetLastError(ERROR_MORE_DATA);
3266 ret = FALSE;
3268 else
3270 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3272 if (dataLen)
3274 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3275 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3276 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3277 0, NULL, &name->u.FullName, pcbStructInfo,
3278 name->u.FullName.rgAltEntry);
3280 else
3281 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3285 else
3287 SetLastError(CRYPT_E_ASN1_BADTAG);
3288 ret = FALSE;
3290 return ret;
3293 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3294 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3295 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3297 struct AsnDecodeSequenceItem items[] = {
3298 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3299 DistPointName), CRYPT_AsnDecodeDistPointName,
3300 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3301 DistPointName.u.FullName.rgAltEntry), 0 },
3302 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3303 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3304 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3305 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3306 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3307 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3309 BOOL ret;
3311 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3312 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3313 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3314 return ret;
3317 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3318 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3319 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3321 BOOL ret;
3323 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3324 pDecodePara, pvStructInfo, *pcbStructInfo);
3326 __TRY
3328 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3329 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3330 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3332 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3333 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3335 __EXCEPT_PAGE_FAULT
3337 SetLastError(STATUS_ACCESS_VIOLATION);
3338 ret = FALSE;
3340 __ENDTRY
3341 return ret;
3344 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3345 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3346 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3348 BOOL ret;
3350 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3351 pDecodePara, pvStructInfo, *pcbStructInfo);
3353 __TRY
3355 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3356 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3358 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3359 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3361 __EXCEPT_PAGE_FAULT
3363 SetLastError(STATUS_ACCESS_VIOLATION);
3364 ret = FALSE;
3366 __ENDTRY
3367 return ret;
3370 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3371 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3372 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3374 BOOL ret;
3376 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3377 pDecodePara, pvStructInfo, *pcbStructInfo);
3379 __TRY
3381 struct AsnDecodeSequenceItem items[] = {
3382 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3383 DistPointName), CRYPT_AsnDecodeDistPointName,
3384 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3385 offsetof(CRL_ISSUING_DIST_POINT,
3386 DistPointName.u.FullName.rgAltEntry), 0 },
3387 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3388 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3389 FALSE, 0 },
3390 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3391 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3392 FALSE, 0 },
3393 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3394 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3395 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3396 OnlySomeReasonFlags.pbData), 0 },
3397 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3398 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3401 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3402 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3403 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3405 __EXCEPT_PAGE_FAULT
3407 SetLastError(STATUS_ACCESS_VIOLATION);
3408 ret = FALSE;
3410 __ENDTRY
3411 return ret;
3414 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3415 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3416 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3418 static HCRYPTOIDFUNCSET set = NULL;
3419 BOOL ret = FALSE;
3420 CryptDecodeObjectExFunc decodeFunc = NULL;
3421 HCRYPTOIDFUNCADDR hFunc = NULL;
3423 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
3424 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
3425 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3427 if (!pvStructInfo && !pcbStructInfo)
3429 SetLastError(ERROR_INVALID_PARAMETER);
3430 return FALSE;
3432 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3433 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3435 SetLastError(ERROR_FILE_NOT_FOUND);
3436 return FALSE;
3438 if (!cbEncoded)
3440 SetLastError(CRYPT_E_ASN1_EOD);
3441 return FALSE;
3443 if (cbEncoded > MAX_ENCODED_LEN)
3445 SetLastError(CRYPT_E_ASN1_LARGE);
3446 return FALSE;
3449 SetLastError(NOERROR);
3450 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3451 *(BYTE **)pvStructInfo = NULL;
3452 if (!HIWORD(lpszStructType))
3454 switch (LOWORD(lpszStructType))
3456 case (WORD)X509_CERT:
3457 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3458 break;
3459 case (WORD)X509_CERT_TO_BE_SIGNED:
3460 decodeFunc = CRYPT_AsnDecodeCert;
3461 break;
3462 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3463 decodeFunc = CRYPT_AsnDecodeCRL;
3464 break;
3465 case (WORD)X509_EXTENSIONS:
3466 decodeFunc = CRYPT_AsnDecodeExtensions;
3467 break;
3468 case (WORD)X509_NAME_VALUE:
3469 decodeFunc = CRYPT_AsnDecodeNameValue;
3470 break;
3471 case (WORD)X509_NAME:
3472 decodeFunc = CRYPT_AsnDecodeName;
3473 break;
3474 case (WORD)X509_PUBLIC_KEY_INFO:
3475 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
3476 break;
3477 case (WORD)X509_ALTERNATE_NAME:
3478 decodeFunc = CRYPT_AsnDecodeAltName;
3479 break;
3480 case (WORD)X509_BASIC_CONSTRAINTS:
3481 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3482 break;
3483 case (WORD)X509_BASIC_CONSTRAINTS2:
3484 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3485 break;
3486 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3487 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3488 break;
3489 case (WORD)X509_UNICODE_NAME:
3490 decodeFunc = CRYPT_AsnDecodeUnicodeName;
3491 break;
3492 case (WORD)X509_UNICODE_NAME_VALUE:
3493 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
3494 break;
3495 case (WORD)X509_OCTET_STRING:
3496 decodeFunc = CRYPT_AsnDecodeOctets;
3497 break;
3498 case (WORD)X509_BITS:
3499 case (WORD)X509_KEY_USAGE:
3500 decodeFunc = CRYPT_AsnDecodeBits;
3501 break;
3502 case (WORD)X509_INTEGER:
3503 decodeFunc = CRYPT_AsnDecodeInt;
3504 break;
3505 case (WORD)X509_MULTI_BYTE_INTEGER:
3506 decodeFunc = CRYPT_AsnDecodeInteger;
3507 break;
3508 case (WORD)X509_MULTI_BYTE_UINT:
3509 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3510 break;
3511 case (WORD)X509_ENUMERATED:
3512 decodeFunc = CRYPT_AsnDecodeEnumerated;
3513 break;
3514 case (WORD)X509_CHOICE_OF_TIME:
3515 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3516 break;
3517 case (WORD)X509_SEQUENCE_OF_ANY:
3518 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3519 break;
3520 case (WORD)PKCS_UTC_TIME:
3521 decodeFunc = CRYPT_AsnDecodeUtcTime;
3522 break;
3523 case (WORD)X509_CRL_DIST_POINTS:
3524 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3525 break;
3526 case (WORD)X509_ENHANCED_KEY_USAGE:
3527 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3528 break;
3529 case (WORD)X509_ISSUING_DIST_POINT:
3530 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3531 break;
3532 default:
3533 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3536 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3537 decodeFunc = CRYPT_AsnDecodeExtensions;
3538 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3539 decodeFunc = CRYPT_AsnDecodeUtcTime;
3540 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3541 decodeFunc = CRYPT_AsnDecodeEnumerated;
3542 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3543 decodeFunc = CRYPT_AsnDecodeBits;
3544 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3545 decodeFunc = CRYPT_AsnDecodeOctets;
3546 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3547 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3548 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3549 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3550 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3551 decodeFunc = CRYPT_AsnDecodeAltName;
3552 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3553 decodeFunc = CRYPT_AsnDecodeAltName;
3554 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3555 decodeFunc = CRYPT_AsnDecodeAltName;
3556 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3557 decodeFunc = CRYPT_AsnDecodeAltName;
3558 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3559 decodeFunc = CRYPT_AsnDecodeAltName;
3560 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3561 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3562 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3563 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3564 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3565 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3566 else
3567 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3568 debugstr_a(lpszStructType));
3569 if (!decodeFunc)
3571 if (!set)
3572 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
3573 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3574 (void **)&decodeFunc, &hFunc);
3576 if (decodeFunc)
3577 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3578 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3579 else
3580 SetLastError(ERROR_FILE_NOT_FOUND);
3581 if (hFunc)
3582 CryptFreeOIDFunctionAddress(hFunc, 0);
3583 return ret;