shell32/tests: Hack SHGetFileInfo() so it does not crash and add a test for it.
[wine/hacks.git] / dlls / crypt32 / decode.c
blobcb83a80a0bb4ecefa24f6d9f79b1a2407a4da18e
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. Also doesn't check tag, assumes the caller has checked
117 * it.
119 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
120 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
121 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
122 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
123 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
124 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
125 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
126 void *pvStructInfo, DWORD *pcbStructInfo);
128 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
129 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
130 DWORD *pcbStructInfo)
132 static HCRYPTOIDFUNCSET set = NULL;
133 BOOL ret = FALSE;
134 CryptDecodeObjectFunc pCryptDecodeObject;
135 HCRYPTOIDFUNCADDR hFunc;
137 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
138 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
139 pvStructInfo, pcbStructInfo);
141 if (!pvStructInfo && !pcbStructInfo)
143 SetLastError(ERROR_INVALID_PARAMETER);
144 return FALSE;
147 /* Try registered DLL first.. */
148 if (!set)
149 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
150 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
151 (void **)&pCryptDecodeObject, &hFunc);
152 if (pCryptDecodeObject)
154 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
155 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
156 CryptFreeOIDFunctionAddress(hFunc, 0);
158 else
160 /* If not, use CryptDecodeObjectEx */
161 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
162 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
164 return ret;
167 /* Gets the number of length bytes from the given (leading) length byte */
168 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
170 /* Helper function to get the encoded length of the data starting at pbEncoded,
171 * where pbEncoded[0] is the tag. If the data are too short to contain a
172 * length or if the length is too large for cbEncoded, sets an appropriate
173 * error code and returns FALSE.
175 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
176 DWORD *len)
178 BOOL ret;
180 if (cbEncoded <= 1)
182 SetLastError(CRYPT_E_ASN1_CORRUPT);
183 ret = FALSE;
185 else if (pbEncoded[1] <= 0x7f)
187 if (pbEncoded[1] + 1 > cbEncoded)
189 SetLastError(CRYPT_E_ASN1_EOD);
190 ret = FALSE;
192 else
194 *len = pbEncoded[1];
195 ret = TRUE;
198 else
200 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
202 if (lenLen > sizeof(DWORD) + 1)
204 SetLastError(CRYPT_E_ASN1_LARGE);
205 ret = FALSE;
207 else if (lenLen + 2 > cbEncoded)
209 SetLastError(CRYPT_E_ASN1_CORRUPT);
210 ret = FALSE;
212 else
214 DWORD out = 0;
216 pbEncoded += 2;
217 while (--lenLen)
219 out <<= 8;
220 out |= *pbEncoded++;
222 if (out + lenLen + 1 > cbEncoded)
224 SetLastError(CRYPT_E_ASN1_EOD);
225 ret = FALSE;
227 else
229 *len = out;
230 ret = TRUE;
234 return ret;
237 /* Helper function to check *pcbStructInfo, set it to the required size, and
238 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
239 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
240 * pointer to the newly allocated memory.
242 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
243 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
244 DWORD bytesNeeded)
246 BOOL ret = TRUE;
248 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
250 if (pDecodePara && pDecodePara->pfnAlloc)
251 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
252 else
253 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
254 if (!*(BYTE **)pvStructInfo)
255 ret = FALSE;
256 else
257 *pcbStructInfo = bytesNeeded;
259 else if (*pcbStructInfo < bytesNeeded)
261 *pcbStructInfo = bytesNeeded;
262 SetLastError(ERROR_MORE_DATA);
263 ret = FALSE;
265 return ret;
268 /* tag:
269 * The expected tag of the item. If tag is 0, decodeFunc is called
270 * regardless of the tag value seen.
271 * offset:
272 * A sequence is decoded into a struct. The offset member is the
273 * offset of this item within that struct.
274 * decodeFunc:
275 * The decoder function to use. If this is NULL, then the member isn't
276 * decoded, but minSize space is reserved for it.
277 * minSize:
278 * The minimum amount of space occupied after decoding. You must set this.
279 * optional:
280 * If true, and the tag doesn't match the expected tag for this item,
281 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
282 * filled with 0 for this member.
283 * hasPointer, pointerOffset, minSize:
284 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
285 * the offset within the (outer) struct of the data pointer (or to the
286 * first data pointer, if more than one exist).
287 * size:
288 * Used by CRYPT_AsnDecodeSequence, not for your use.
290 struct AsnDecodeSequenceItem
292 BYTE tag;
293 DWORD offset;
294 CryptDecodeObjectExFunc decodeFunc;
295 DWORD minSize;
296 BOOL optional;
297 BOOL hasPointer;
298 DWORD pointerOffset;
299 DWORD size;
302 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
303 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
304 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData)
306 BOOL ret;
307 DWORD i;
308 const BYTE *ptr;
310 ptr = pbEncoded + 1 + GET_LEN_BYTES(pbEncoded[1]);
311 for (i = 0, ret = TRUE; ret && i < cItem; i++)
313 if (cbEncoded - (ptr - pbEncoded) != 0)
315 DWORD nextItemLen;
317 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
318 &nextItemLen)))
320 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
322 if (ptr[0] == items[i].tag || !items[i].tag)
324 if (nextData && pvStructInfo && items[i].hasPointer)
326 TRACE("Setting next pointer to %p\n",
327 nextData);
328 *(BYTE **)((BYTE *)pvStructInfo +
329 items[i].pointerOffset) = nextData;
331 if (items[i].decodeFunc)
333 if (pvStructInfo)
334 TRACE("decoding item %d\n", i);
335 else
336 TRACE("sizing item %d\n", i);
337 ret = items[i].decodeFunc(dwCertEncodingType,
338 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
339 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
340 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
341 : NULL, &items[i].size);
342 if (ret)
344 if (nextData && items[i].hasPointer &&
345 items[i].size > items[i].minSize)
347 nextData += items[i].size - items[i].minSize;
348 /* align nextData to DWORD boundaries */
349 if (items[i].size % sizeof(DWORD))
350 nextData += sizeof(DWORD) - items[i].size %
351 sizeof(DWORD);
353 /* Account for alignment padding */
354 if (items[i].size % sizeof(DWORD))
355 items[i].size += sizeof(DWORD) -
356 items[i].size % sizeof(DWORD);
357 ptr += 1 + nextItemLenBytes + nextItemLen;
359 else if (items[i].optional &&
360 GetLastError() == CRYPT_E_ASN1_BADTAG)
362 TRACE("skipping optional item %d\n", i);
363 items[i].size = items[i].minSize;
364 SetLastError(NOERROR);
365 ret = TRUE;
367 else
368 TRACE("item %d failed: %08x\n", i,
369 GetLastError());
371 else
372 items[i].size = items[i].minSize;
374 else if (items[i].optional)
376 TRACE("skipping optional item %d\n", i);
377 items[i].size = items[i].minSize;
379 else
381 TRACE("tag %02x doesn't match expected %02x\n",
382 ptr[0], items[i].tag);
383 SetLastError(CRYPT_E_ASN1_BADTAG);
384 ret = FALSE;
388 else if (items[i].optional)
390 TRACE("missing optional item %d, skipping\n", i);
391 items[i].size = items[i].minSize;
393 else
395 TRACE("not enough bytes for item %d, failing\n", i);
396 SetLastError(CRYPT_E_ASN1_CORRUPT);
397 ret = FALSE;
400 if (cbEncoded - (ptr - pbEncoded) != 0)
402 TRACE("%d remaining bytes, failing\n", cbEncoded -
403 (ptr - pbEncoded));
404 SetLastError(CRYPT_E_ASN1_CORRUPT);
405 ret = FALSE;
407 return ret;
410 /* This decodes an arbitrary sequence into a contiguous block of memory
411 * (basically, a struct.) Each element being decoded is described by a struct
412 * AsnDecodeSequenceItem, see above.
413 * startingPointer is an optional pointer to the first place where dynamic
414 * data will be stored. If you know the starting offset, you may pass it
415 * here. Otherwise, pass NULL, and one will be inferred from the items.
416 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
417 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
419 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
420 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
421 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
422 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
424 BOOL ret;
426 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
427 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
428 startingPointer);
430 if (pbEncoded[0] == ASN_SEQUENCE)
432 DWORD dataLen;
434 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
436 DWORD i;
438 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
439 cbEncoded, dwFlags, NULL, NULL);
440 if (ret)
442 DWORD bytesNeeded = 0, structSize = 0;
444 for (i = 0; i < cItem; i++)
446 bytesNeeded += items[i].size;
447 structSize += items[i].minSize;
449 if (!pvStructInfo)
450 *pcbStructInfo = bytesNeeded;
451 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
452 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
454 BYTE *nextData;
456 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
457 pvStructInfo = *(BYTE **)pvStructInfo;
458 if (startingPointer)
459 nextData = (BYTE *)startingPointer;
460 else
461 nextData = (BYTE *)pvStructInfo + structSize;
462 memset(pvStructInfo, 0, structSize);
463 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
464 pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
469 else
471 SetLastError(CRYPT_E_ASN1_BADTAG);
472 ret = FALSE;
474 TRACE("returning %d (%08x)\n", ret, GetLastError());
475 return ret;
478 /* tag:
479 * The expected tag of the entire encoded array (usually a variant
480 * of ASN_SETOF or ASN_SEQUENCEOF.)
481 * decodeFunc:
482 * used to decode each item in the array
483 * itemSize:
484 * is the minimum size of each decoded item
485 * hasPointer:
486 * indicates whether each item has a dynamic pointer
487 * pointerOffset:
488 * indicates the offset within itemSize at which the pointer exists
490 struct AsnArrayDescriptor
492 BYTE tag;
493 CryptDecodeObjectExFunc decodeFunc;
494 DWORD itemSize;
495 BOOL hasPointer;
496 DWORD pointerOffset;
499 struct AsnArrayItemSize
501 DWORD encodedLen;
502 DWORD size;
505 /* Decodes an array of like types into a struct GenericArray.
506 * The layout and decoding of the array are described by a struct
507 * AsnArrayDescriptor.
509 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
510 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
511 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
512 void *startingPointer)
514 BOOL ret = TRUE;
516 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
517 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
518 startingPointer);
520 if (pbEncoded[0] == arrayDesc->tag)
522 DWORD dataLen;
524 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
526 DWORD bytesNeeded, cItems = 0;
527 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
528 /* There can be arbitrarily many items, but there is often only one.
530 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
532 bytesNeeded = sizeof(struct GenericArray);
533 if (dataLen)
535 const BYTE *ptr;
537 for (ptr = pbEncoded + 1 + lenBytes; ret &&
538 ptr - pbEncoded - 1 - lenBytes < dataLen; )
540 DWORD itemLenBytes, itemDataLen, size;
542 itemLenBytes = GET_LEN_BYTES(ptr[1]);
543 /* Each item decoded may not tolerate extraneous bytes, so
544 * get the length of the next element and pass it directly.
546 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
547 &itemDataLen);
548 if (ret)
549 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
550 1 + itemLenBytes + itemDataLen,
551 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
552 &size);
553 if (ret)
555 DWORD nextLen;
557 cItems++;
558 if (itemSizes != &itemSize)
559 itemSizes = CryptMemRealloc(itemSizes,
560 cItems * sizeof(struct AsnArrayItemSize));
561 else
563 itemSizes =
564 CryptMemAlloc(
565 cItems * sizeof(struct AsnArrayItemSize));
566 if (itemSizes)
567 memcpy(itemSizes, &itemSize, sizeof(itemSize));
569 if (itemSizes)
571 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
572 + itemDataLen;
573 itemSizes[cItems - 1].size = size;
574 bytesNeeded += size;
575 ret = CRYPT_GetLen(ptr,
576 cbEncoded - (ptr - pbEncoded), &nextLen);
577 if (ret)
578 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
580 else
581 ret = FALSE;
585 if (ret)
587 if (!pvStructInfo)
588 *pcbStructInfo = bytesNeeded;
589 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
590 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
592 DWORD i;
593 BYTE *nextData;
594 const BYTE *ptr;
595 struct GenericArray *array;
597 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
598 pvStructInfo = *(BYTE **)pvStructInfo;
599 array = (struct GenericArray *)pvStructInfo;
600 array->cItems = cItems;
601 if (startingPointer)
602 array->rgItems = startingPointer;
603 else
604 array->rgItems = (BYTE *)array +
605 sizeof(struct GenericArray);
606 nextData = (BYTE *)array->rgItems +
607 array->cItems * arrayDesc->itemSize;
608 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
609 i < cItems && ptr - pbEncoded - 1 - lenBytes <
610 dataLen; i++)
612 if (arrayDesc->hasPointer)
613 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
614 + arrayDesc->pointerOffset) = nextData;
615 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
616 itemSizes[i].encodedLen,
617 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
618 array->rgItems + i * arrayDesc->itemSize,
619 &itemSizes[i].size);
620 if (ret)
622 DWORD nextLen;
624 nextData += itemSizes[i].size - arrayDesc->itemSize;
625 ret = CRYPT_GetLen(ptr,
626 cbEncoded - (ptr - pbEncoded), &nextLen);
627 if (ret)
628 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
633 if (itemSizes != &itemSize)
634 CryptMemFree(itemSizes);
637 else
639 SetLastError(CRYPT_E_ASN1_BADTAG);
640 ret = FALSE;
642 return ret;
645 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
646 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
647 * to CRYPT_E_ASN1_CORRUPT.
648 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
649 * set!
651 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
652 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
653 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
655 BOOL ret;
656 DWORD dataLen;
658 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
660 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
661 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
663 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
664 bytesNeeded += 1 + lenBytes + dataLen;
666 if (!pvStructInfo)
667 *pcbStructInfo = bytesNeeded;
668 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
669 pvStructInfo, pcbStructInfo, bytesNeeded)))
671 CRYPT_DER_BLOB *blob;
673 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
674 pvStructInfo = *(BYTE **)pvStructInfo;
675 blob = (CRYPT_DER_BLOB *)pvStructInfo;
676 blob->cbData = 1 + lenBytes + dataLen;
677 if (blob->cbData)
679 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
680 blob->pbData = (BYTE *)pbEncoded;
681 else
683 assert(blob->pbData);
684 memcpy(blob->pbData, pbEncoded, blob->cbData);
687 else
689 SetLastError(CRYPT_E_ASN1_CORRUPT);
690 ret = FALSE;
694 return ret;
697 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
698 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
699 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
700 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
702 BOOL ret;
704 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
705 pDecodePara, pvStructInfo, *pcbStructInfo);
707 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
708 * place.
710 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
711 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
712 pvStructInfo, pcbStructInfo);
713 if (ret && pvStructInfo)
715 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
717 if (blob->cbData)
719 DWORD i;
720 BYTE temp;
722 for (i = 0; i < blob->cbData / 2; i++)
724 temp = blob->pbData[i];
725 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
726 blob->pbData[blob->cbData - i - 1] = temp;
730 TRACE("returning %d (%08x)\n", ret, GetLastError());
731 return ret;
734 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
735 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
736 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
738 BOOL ret = TRUE;
740 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
741 pDecodePara, pvStructInfo, *pcbStructInfo);
743 __TRY
745 struct AsnDecodeSequenceItem items[] = {
746 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
747 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
748 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
749 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
750 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
751 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
752 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
753 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
754 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
755 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
758 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
759 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
760 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
761 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
762 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
764 __EXCEPT_PAGE_FAULT
766 SetLastError(STATUS_ACCESS_VIOLATION);
767 ret = FALSE;
769 __ENDTRY
771 TRACE("Returning %d (%08x)\n", ret, GetLastError());
772 return ret;
775 /* Internal function */
776 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
777 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
778 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
780 BOOL ret;
781 DWORD dataLen;
783 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
785 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
787 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
788 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
789 pvStructInfo, pcbStructInfo);
791 return ret;
794 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
795 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
796 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
798 BOOL ret;
800 struct AsnDecodeSequenceItem items[] = {
801 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
802 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
803 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
804 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
807 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
808 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
809 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
810 return ret;
813 /* Internal function */
814 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
815 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
816 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
818 BOOL ret;
819 DWORD dataLen;
821 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
823 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
825 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
826 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
827 pDecodePara, pvStructInfo, pcbStructInfo);
829 return ret;
832 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
833 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
834 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
836 BOOL ret = TRUE;
837 struct AsnDecodeSequenceItem items[] = {
838 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
839 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
840 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
841 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
842 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
843 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
844 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
845 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
846 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
847 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
848 Issuer.pbData) },
849 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
850 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
851 FALSE, 0 },
852 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
853 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
854 Subject.pbData) },
855 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
856 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
857 FALSE, TRUE, offsetof(CERT_INFO,
858 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
859 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
860 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
861 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
862 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
863 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
864 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
865 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
866 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
867 offsetof(CERT_INFO, rgExtension), 0 },
870 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
871 pDecodePara, pvStructInfo, *pcbStructInfo);
873 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
874 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
875 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
877 TRACE("Returning %d (%08x)\n", ret, GetLastError());
878 return ret;
881 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
882 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
883 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
885 BOOL ret = TRUE;
887 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
888 pDecodePara, pvStructInfo, *pcbStructInfo);
890 __TRY
892 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
893 DWORD size = 0;
895 /* First try to decode it as a signed cert. */
896 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
897 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
898 (BYTE *)&signedCert, &size);
899 if (ret)
901 size = 0;
902 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
903 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
904 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
905 pcbStructInfo);
906 LocalFree(signedCert);
908 /* Failing that, try it as an unsigned cert */
909 if (!ret)
911 size = 0;
912 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
913 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
914 pDecodePara, pvStructInfo, pcbStructInfo);
917 __EXCEPT_PAGE_FAULT
919 SetLastError(STATUS_ACCESS_VIOLATION);
920 ret = FALSE;
922 __ENDTRY
924 TRACE("Returning %d (%08x)\n", ret, GetLastError());
925 return ret;
928 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
929 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
930 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
932 BOOL ret;
933 struct AsnDecodeSequenceItem items[] = {
934 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
935 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
936 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
937 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
938 sizeof(FILETIME), FALSE, FALSE, 0 },
939 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
940 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
941 offsetof(CRL_ENTRY, rgExtension), 0 },
943 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
945 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
946 *pcbStructInfo);
948 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
949 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
950 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
951 return ret;
954 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
955 * been set prior to calling.
957 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
958 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
959 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
961 BOOL ret;
962 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
963 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
964 offsetof(CRL_ENTRY, SerialNumber.pbData) };
965 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
967 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
968 pDecodePara, pvStructInfo, *pcbStructInfo);
970 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
971 pDecodePara, pvStructInfo, pcbStructInfo,
972 entries ? entries->rgItems : NULL);
973 TRACE("Returning %d (%08x)\n", ret, GetLastError());
974 return ret;
977 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
978 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
979 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
981 struct AsnDecodeSequenceItem items[] = {
982 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
983 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
984 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
985 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
986 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
987 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
988 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
989 Issuer.pbData) },
990 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
991 sizeof(FILETIME), FALSE, FALSE, 0 },
992 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
993 sizeof(FILETIME), TRUE, FALSE, 0 },
994 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
995 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
996 offsetof(CRL_INFO, rgCRLEntry), 0 },
997 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
998 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
999 offsetof(CRL_INFO, rgExtension), 0 },
1001 BOOL ret = TRUE;
1003 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1004 pDecodePara, pvStructInfo, *pcbStructInfo);
1006 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1007 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1008 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1010 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1011 return ret;
1014 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1015 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1016 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1018 BOOL ret = TRUE;
1020 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1021 pDecodePara, pvStructInfo, *pcbStructInfo);
1023 __TRY
1025 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1026 DWORD size = 0;
1028 /* First try to decode it as a signed crl. */
1029 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1030 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1031 (BYTE *)&signedCrl, &size);
1032 if (ret)
1034 size = 0;
1035 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1036 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1037 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1038 pvStructInfo, pcbStructInfo);
1039 LocalFree(signedCrl);
1041 /* Failing that, try it as an unsigned crl */
1042 if (!ret)
1044 size = 0;
1045 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1046 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1047 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1050 __EXCEPT_PAGE_FAULT
1052 SetLastError(STATUS_ACCESS_VIOLATION);
1053 ret = FALSE;
1055 __ENDTRY
1057 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1058 return ret;
1061 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1062 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1063 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1065 BOOL ret = TRUE;
1067 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1068 pDecodePara, pvStructInfo, *pcbStructInfo);
1070 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1072 DWORD dataLen;
1074 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1076 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1077 DWORD bytesNeeded = sizeof(LPSTR);
1079 if (dataLen)
1081 /* The largest possible string for the first two components
1082 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1084 char firstTwo[6];
1085 const BYTE *ptr;
1087 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1088 pbEncoded[1 + lenBytes] / 40,
1089 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1090 * 40);
1091 bytesNeeded += strlen(firstTwo) + 1;
1092 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1093 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1095 /* large enough for ".4000000" */
1096 char str[9];
1097 int val = 0;
1099 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1100 (*ptr & 0x80))
1102 val <<= 7;
1103 val |= *ptr & 0x7f;
1104 ptr++;
1106 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1107 (*ptr & 0x80))
1109 SetLastError(CRYPT_E_ASN1_CORRUPT);
1110 ret = FALSE;
1112 else
1114 val <<= 7;
1115 val |= *ptr++;
1116 snprintf(str, sizeof(str), ".%d", val);
1117 bytesNeeded += strlen(str);
1121 if (!pvStructInfo)
1122 *pcbStructInfo = bytesNeeded;
1123 else if (*pcbStructInfo < bytesNeeded)
1125 *pcbStructInfo = bytesNeeded;
1126 SetLastError(ERROR_MORE_DATA);
1127 ret = FALSE;
1129 else
1131 if (dataLen)
1133 const BYTE *ptr;
1134 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1136 *pszObjId = 0;
1137 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1138 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1139 40) * 40);
1140 pszObjId += strlen(pszObjId);
1141 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1142 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1144 int val = 0;
1146 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1147 (*ptr & 0x80))
1149 val <<= 7;
1150 val |= *ptr & 0x7f;
1151 ptr++;
1153 val <<= 7;
1154 val |= *ptr++;
1155 sprintf(pszObjId, ".%d", val);
1156 pszObjId += strlen(pszObjId);
1159 else
1160 *(LPSTR *)pvStructInfo = NULL;
1161 *pcbStructInfo = bytesNeeded;
1165 return ret;
1168 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1169 * ahead of time!
1171 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1172 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1173 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1175 struct AsnDecodeSequenceItem items[] = {
1176 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1177 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1178 offsetof(CERT_EXTENSION, pszObjId), 0 },
1179 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1180 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1181 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1182 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1183 offsetof(CERT_EXTENSION, Value.pbData) },
1185 BOOL ret = TRUE;
1186 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1188 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1189 *pcbStructInfo);
1191 if (ext)
1192 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1193 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1194 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1195 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1196 if (ext)
1197 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1198 debugstr_a(ext->pszObjId));
1199 TRACE("returning %d (%08x)\n", ret, GetLastError());
1200 return ret;
1203 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1204 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1205 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1207 BOOL ret = TRUE;
1208 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1209 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1210 offsetof(CERT_EXTENSION, pszObjId) };
1211 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1213 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1214 pDecodePara, pvStructInfo, *pcbStructInfo);
1216 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1217 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1218 return ret;
1221 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1222 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1223 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1225 BOOL ret = TRUE;
1227 __TRY
1229 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1230 lpszStructType, pbEncoded, cbEncoded,
1231 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1232 if (ret && pvStructInfo)
1234 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1235 pcbStructInfo, *pcbStructInfo);
1236 if (ret)
1238 CERT_EXTENSIONS *exts;
1240 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1241 pvStructInfo = *(BYTE **)pvStructInfo;
1242 exts = (CERT_EXTENSIONS *)pvStructInfo;
1243 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1244 sizeof(CERT_EXTENSIONS));
1245 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1246 lpszStructType, pbEncoded, cbEncoded,
1247 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1248 pcbStructInfo);
1252 __EXCEPT_PAGE_FAULT
1254 SetLastError(STATUS_ACCESS_VIOLATION);
1255 ret = FALSE;
1257 __ENDTRY
1258 return ret;
1261 /* Warning: this assumes the address of value->Value.pbData is already set, in
1262 * order to avoid overwriting memory. (In some cases, it may change it, if it
1263 * doesn't copy anything to memory.) Be sure to set it correctly!
1265 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1266 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1267 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1269 BOOL ret = TRUE;
1270 DWORD dataLen;
1271 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1273 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1275 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1276 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1278 switch (pbEncoded[0])
1280 case ASN_OCTETSTRING:
1281 valueType = CERT_RDN_OCTET_STRING;
1282 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1283 bytesNeeded += dataLen;
1284 break;
1285 case ASN_NUMERICSTRING:
1286 valueType = CERT_RDN_NUMERIC_STRING;
1287 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1288 bytesNeeded += dataLen;
1289 break;
1290 case ASN_PRINTABLESTRING:
1291 valueType = CERT_RDN_PRINTABLE_STRING;
1292 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1293 bytesNeeded += dataLen;
1294 break;
1295 case ASN_IA5STRING:
1296 valueType = CERT_RDN_IA5_STRING;
1297 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1298 bytesNeeded += dataLen;
1299 break;
1300 case ASN_T61STRING:
1301 valueType = CERT_RDN_T61_STRING;
1302 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1303 bytesNeeded += dataLen;
1304 break;
1305 case ASN_VIDEOTEXSTRING:
1306 valueType = CERT_RDN_VIDEOTEX_STRING;
1307 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1308 bytesNeeded += dataLen;
1309 break;
1310 case ASN_GRAPHICSTRING:
1311 valueType = CERT_RDN_GRAPHIC_STRING;
1312 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1313 bytesNeeded += dataLen;
1314 break;
1315 case ASN_VISIBLESTRING:
1316 valueType = CERT_RDN_VISIBLE_STRING;
1317 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1318 bytesNeeded += dataLen;
1319 break;
1320 case ASN_GENERALSTRING:
1321 valueType = CERT_RDN_GENERAL_STRING;
1322 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1323 bytesNeeded += dataLen;
1324 break;
1325 case ASN_UNIVERSALSTRING:
1326 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1327 SetLastError(CRYPT_E_ASN1_BADTAG);
1328 return FALSE;
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 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1337 break;
1338 default:
1339 SetLastError(CRYPT_E_ASN1_BADTAG);
1340 return FALSE;
1343 if (!value)
1344 *pcbStructInfo = bytesNeeded;
1345 else if (*pcbStructInfo < bytesNeeded)
1347 *pcbStructInfo = bytesNeeded;
1348 SetLastError(ERROR_MORE_DATA);
1349 ret = FALSE;
1351 else
1353 *pcbStructInfo = bytesNeeded;
1354 value->dwValueType = valueType;
1355 if (dataLen)
1357 DWORD i;
1359 assert(value->Value.pbData);
1360 switch (pbEncoded[0])
1362 case ASN_OCTETSTRING:
1363 case ASN_NUMERICSTRING:
1364 case ASN_PRINTABLESTRING:
1365 case ASN_IA5STRING:
1366 case ASN_T61STRING:
1367 case ASN_VIDEOTEXSTRING:
1368 case ASN_GRAPHICSTRING:
1369 case ASN_VISIBLESTRING:
1370 case ASN_GENERALSTRING:
1371 value->Value.cbData = dataLen;
1372 if (dataLen)
1374 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1375 memcpy(value->Value.pbData,
1376 pbEncoded + 1 + lenBytes, dataLen);
1377 else
1378 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1379 lenBytes;
1381 break;
1382 case ASN_BMPSTRING:
1384 LPWSTR str = (LPWSTR)value->Value.pbData;
1386 value->Value.cbData = dataLen;
1387 for (i = 0; i < dataLen / 2; i++)
1388 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1389 pbEncoded[1 + lenBytes + 2 * i + 1];
1390 break;
1392 case ASN_UTF8STRING:
1394 LPWSTR str = (LPWSTR)value->Value.pbData;
1396 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1397 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1398 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1399 break;
1403 else
1405 value->Value.cbData = 0;
1406 value->Value.pbData = NULL;
1410 return ret;
1413 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1414 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1415 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1417 BOOL ret = TRUE;
1419 __TRY
1421 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1422 lpszStructType, pbEncoded, cbEncoded,
1423 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1424 if (ret && pvStructInfo)
1426 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1427 pcbStructInfo, *pcbStructInfo);
1428 if (ret)
1430 CERT_NAME_VALUE *value;
1432 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1433 pvStructInfo = *(BYTE **)pvStructInfo;
1434 value = (CERT_NAME_VALUE *)pvStructInfo;
1435 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1436 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1437 lpszStructType, pbEncoded, cbEncoded,
1438 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1439 pcbStructInfo);
1443 __EXCEPT_PAGE_FAULT
1445 SetLastError(STATUS_ACCESS_VIOLATION);
1446 ret = FALSE;
1448 __ENDTRY
1449 return ret;
1452 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1453 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1454 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1455 void *pvStructInfo, DWORD *pcbStructInfo)
1457 BOOL ret = TRUE;
1458 DWORD dataLen;
1459 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1461 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1463 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1464 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1466 switch (pbEncoded[0])
1468 case ASN_NUMERICSTRING:
1469 valueType = CERT_RDN_NUMERIC_STRING;
1470 bytesNeeded += dataLen * 2;
1471 break;
1472 case ASN_PRINTABLESTRING:
1473 valueType = CERT_RDN_PRINTABLE_STRING;
1474 bytesNeeded += dataLen * 2;
1475 break;
1476 case ASN_IA5STRING:
1477 valueType = CERT_RDN_IA5_STRING;
1478 bytesNeeded += dataLen * 2;
1479 break;
1480 case ASN_T61STRING:
1481 valueType = CERT_RDN_T61_STRING;
1482 bytesNeeded += dataLen * 2;
1483 break;
1484 case ASN_VIDEOTEXSTRING:
1485 valueType = CERT_RDN_VIDEOTEX_STRING;
1486 bytesNeeded += dataLen * 2;
1487 break;
1488 case ASN_GRAPHICSTRING:
1489 valueType = CERT_RDN_GRAPHIC_STRING;
1490 bytesNeeded += dataLen * 2;
1491 break;
1492 case ASN_VISIBLESTRING:
1493 valueType = CERT_RDN_VISIBLE_STRING;
1494 bytesNeeded += dataLen * 2;
1495 break;
1496 case ASN_GENERALSTRING:
1497 valueType = CERT_RDN_GENERAL_STRING;
1498 bytesNeeded += dataLen * 2;
1499 break;
1500 case ASN_UNIVERSALSTRING:
1501 valueType = CERT_RDN_UNIVERSAL_STRING;
1502 bytesNeeded += dataLen / 2;
1503 break;
1504 case ASN_BMPSTRING:
1505 valueType = CERT_RDN_BMP_STRING;
1506 bytesNeeded += dataLen;
1507 break;
1508 case ASN_UTF8STRING:
1509 valueType = CERT_RDN_UTF8_STRING;
1510 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1511 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1512 break;
1513 default:
1514 SetLastError(CRYPT_E_ASN1_BADTAG);
1515 return FALSE;
1518 if (!value)
1519 *pcbStructInfo = bytesNeeded;
1520 else if (*pcbStructInfo < bytesNeeded)
1522 *pcbStructInfo = bytesNeeded;
1523 SetLastError(ERROR_MORE_DATA);
1524 ret = FALSE;
1526 else
1528 *pcbStructInfo = bytesNeeded;
1529 value->dwValueType = valueType;
1530 if (dataLen)
1532 DWORD i;
1533 LPWSTR str = (LPWSTR)value->Value.pbData;
1535 assert(value->Value.pbData);
1536 switch (pbEncoded[0])
1538 case ASN_NUMERICSTRING:
1539 case ASN_PRINTABLESTRING:
1540 case ASN_IA5STRING:
1541 case ASN_T61STRING:
1542 case ASN_VIDEOTEXSTRING:
1543 case ASN_GRAPHICSTRING:
1544 case ASN_VISIBLESTRING:
1545 case ASN_GENERALSTRING:
1546 value->Value.cbData = dataLen * 2;
1547 for (i = 0; i < dataLen; i++)
1548 str[i] = pbEncoded[1 + lenBytes + i];
1549 break;
1550 case ASN_UNIVERSALSTRING:
1551 value->Value.cbData = dataLen / 2;
1552 for (i = 0; i < dataLen / 4; i++)
1553 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1554 | pbEncoded[1 + lenBytes + 2 * i + 3];
1555 break;
1556 case ASN_BMPSTRING:
1557 value->Value.cbData = dataLen;
1558 for (i = 0; i < dataLen / 2; i++)
1559 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1560 pbEncoded[1 + lenBytes + 2 * i + 1];
1561 break;
1562 case ASN_UTF8STRING:
1563 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1564 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1565 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1566 break;
1569 else
1571 value->Value.cbData = 0;
1572 value->Value.pbData = NULL;
1576 return ret;
1579 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1580 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1581 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1583 BOOL ret = TRUE;
1585 __TRY
1587 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1588 lpszStructType, pbEncoded, cbEncoded,
1589 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1590 if (ret && pvStructInfo)
1592 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1593 pcbStructInfo, *pcbStructInfo);
1594 if (ret)
1596 CERT_NAME_VALUE *value;
1598 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1599 pvStructInfo = *(BYTE **)pvStructInfo;
1600 value = (CERT_NAME_VALUE *)pvStructInfo;
1601 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1602 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1603 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1604 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1605 pcbStructInfo);
1609 __EXCEPT_PAGE_FAULT
1611 SetLastError(STATUS_ACCESS_VIOLATION);
1612 ret = FALSE;
1614 __ENDTRY
1615 return ret;
1618 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1619 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1620 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1622 BOOL ret;
1623 struct AsnDecodeSequenceItem items[] = {
1624 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1625 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1626 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1627 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1628 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1629 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1631 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1633 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1634 pvStructInfo, *pcbStructInfo);
1636 if (attr)
1637 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1638 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1639 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1640 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1641 if (attr)
1643 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1644 debugstr_a(attr->pszObjId));
1645 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1647 TRACE("returning %d (%08x)\n", ret, GetLastError());
1648 return ret;
1651 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1652 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1653 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1655 BOOL ret = TRUE;
1656 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1657 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1658 offsetof(CERT_RDN_ATTR, pszObjId) };
1659 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1661 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1662 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1663 return ret;
1666 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1667 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1668 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1670 BOOL ret = TRUE;
1672 __TRY
1674 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1675 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1676 offsetof(CERT_RDN, rgRDNAttr) };
1678 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1679 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1681 __EXCEPT_PAGE_FAULT
1683 SetLastError(STATUS_ACCESS_VIOLATION);
1684 ret = FALSE;
1686 __ENDTRY
1687 return ret;
1690 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
1691 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1692 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1694 BOOL ret;
1695 struct AsnDecodeSequenceItem items[] = {
1696 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1697 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1698 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1699 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1700 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1701 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1703 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1705 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1706 pvStructInfo, *pcbStructInfo);
1708 if (attr)
1709 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1710 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1711 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1712 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1713 if (attr)
1715 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1716 debugstr_a(attr->pszObjId));
1717 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1719 TRACE("returning %d (%08x)\n", ret, GetLastError());
1720 return ret;
1723 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
1724 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1725 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1727 BOOL ret = TRUE;
1728 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1729 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1730 offsetof(CERT_RDN_ATTR, pszObjId) };
1731 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1733 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1734 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1735 return ret;
1738 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1739 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1740 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1742 BOOL ret = TRUE;
1744 __TRY
1746 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1747 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1748 offsetof(CERT_RDN, rgRDNAttr) };
1750 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1751 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1753 __EXCEPT_PAGE_FAULT
1755 SetLastError(STATUS_ACCESS_VIOLATION);
1756 ret = FALSE;
1758 __ENDTRY
1759 return ret;
1762 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1763 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1764 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1766 BOOL ret = TRUE;
1767 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1769 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1770 pDecodePara, pvStructInfo, *pcbStructInfo);
1772 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1773 bytesNeeded += cbEncoded;
1774 if (!pvStructInfo)
1775 *pcbStructInfo = bytesNeeded;
1776 else if (*pcbStructInfo < bytesNeeded)
1778 SetLastError(ERROR_MORE_DATA);
1779 *pcbStructInfo = bytesNeeded;
1780 ret = FALSE;
1782 else
1784 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1786 *pcbStructInfo = bytesNeeded;
1787 blob->cbData = cbEncoded;
1788 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1789 blob->pbData = (LPBYTE)pbEncoded;
1790 else
1792 assert(blob->pbData);
1793 memcpy(blob->pbData, pbEncoded, blob->cbData);
1796 return ret;
1799 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1800 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1801 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1803 CRYPT_ALGORITHM_IDENTIFIER *algo =
1804 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1805 BOOL ret = TRUE;
1806 struct AsnDecodeSequenceItem items[] = {
1807 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1808 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1809 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1810 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1811 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1812 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1815 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1816 pDecodePara, pvStructInfo, *pcbStructInfo);
1818 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1819 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1820 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1821 if (ret && pvStructInfo)
1823 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1824 debugstr_a(algo->pszObjId));
1826 return ret;
1829 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1830 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1831 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1833 BOOL ret = TRUE;
1834 struct AsnDecodeSequenceItem items[] = {
1835 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1836 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1837 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1838 Algorithm.pszObjId) },
1839 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1840 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1841 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1843 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1845 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1846 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1847 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1848 info->Algorithm.Parameters.pbData : NULL);
1849 return ret;
1852 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1853 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1854 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1856 BOOL ret = TRUE;
1858 __TRY
1860 DWORD bytesNeeded;
1862 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1863 lpszStructType, pbEncoded, cbEncoded,
1864 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1866 if (!pvStructInfo)
1867 *pcbStructInfo = bytesNeeded;
1868 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1869 pvStructInfo, pcbStructInfo, bytesNeeded)))
1871 PCERT_PUBLIC_KEY_INFO info;
1873 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1874 pvStructInfo = *(BYTE **)pvStructInfo;
1875 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1876 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
1877 sizeof(CERT_PUBLIC_KEY_INFO);
1878 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1879 lpszStructType, pbEncoded, cbEncoded,
1880 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1881 &bytesNeeded);
1885 __EXCEPT_PAGE_FAULT
1887 SetLastError(STATUS_ACCESS_VIOLATION);
1888 ret = FALSE;
1890 __ENDTRY
1891 return ret;
1894 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
1895 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1896 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1898 BOOL ret;
1900 if (cbEncoded < 3)
1902 SetLastError(CRYPT_E_ASN1_CORRUPT);
1903 return FALSE;
1905 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
1907 SetLastError(CRYPT_E_ASN1_CORRUPT);
1908 return FALSE;
1910 if (pbEncoded[1] > 1)
1912 SetLastError(CRYPT_E_ASN1_CORRUPT);
1913 return FALSE;
1915 if (!pvStructInfo)
1917 *pcbStructInfo = sizeof(BOOL);
1918 ret = TRUE;
1920 else if (*pcbStructInfo < sizeof(BOOL))
1922 *pcbStructInfo = sizeof(BOOL);
1923 SetLastError(ERROR_MORE_DATA);
1924 ret = FALSE;
1926 else
1928 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
1929 ret = TRUE;
1931 TRACE("returning %d (%08x)\n", ret, GetLastError());
1932 return ret;
1935 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
1936 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1937 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1939 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
1940 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
1941 BOOL ret;
1943 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1944 pDecodePara, pvStructInfo, *pcbStructInfo);
1946 if (cbEncoded < 2)
1948 SetLastError(CRYPT_E_ASN1_CORRUPT);
1949 return FALSE;
1951 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
1953 SetLastError(CRYPT_E_ASN1_BADTAG);
1954 return FALSE;
1956 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1957 if (1 + lenBytes > cbEncoded)
1959 SetLastError(CRYPT_E_ASN1_CORRUPT);
1960 return FALSE;
1962 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1964 switch (pbEncoded[0] & ASN_TYPE_MASK)
1966 case 1: /* rfc822Name */
1967 case 2: /* dNSName */
1968 case 6: /* uniformResourceIdentifier */
1969 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1970 break;
1971 case 7: /* iPAddress */
1972 bytesNeeded += dataLen;
1973 break;
1974 case 8: /* registeredID */
1975 /* FIXME: decode as OID */
1976 case 0: /* otherName */
1977 case 4: /* directoryName */
1978 FIXME("stub\n");
1979 SetLastError(CRYPT_E_ASN1_BADTAG);
1980 ret = FALSE;
1981 break;
1982 case 3: /* x400Address, unimplemented */
1983 case 5: /* ediPartyName, unimplemented */
1984 SetLastError(CRYPT_E_ASN1_BADTAG);
1985 ret = FALSE;
1986 break;
1987 default:
1988 SetLastError(CRYPT_E_ASN1_CORRUPT);
1989 ret = FALSE;
1991 if (ret)
1993 if (!entry)
1994 *pcbStructInfo = bytesNeeded;
1995 else if (*pcbStructInfo < bytesNeeded)
1997 *pcbStructInfo = bytesNeeded;
1998 SetLastError(ERROR_MORE_DATA);
1999 ret = FALSE;
2001 else
2003 *pcbStructInfo = bytesNeeded;
2004 /* MS used values one greater than the asn1 ones.. sigh */
2005 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2006 switch (pbEncoded[0] & ASN_TYPE_MASK)
2008 case 1: /* rfc822Name */
2009 case 2: /* dNSName */
2010 case 6: /* uniformResourceIdentifier */
2012 DWORD i;
2014 for (i = 0; i < dataLen; i++)
2015 entry->u.pwszURL[i] =
2016 (WCHAR)pbEncoded[1 + lenBytes + i];
2017 entry->u.pwszURL[i] = 0;
2018 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2019 debugstr_w(entry->u.pwszURL));
2020 break;
2022 case 7: /* iPAddress */
2023 /* The next data pointer is in the pwszURL spot, that is,
2024 * the first 4 bytes. Need to move it to the next spot.
2026 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2027 entry->u.IPAddress.cbData = dataLen;
2028 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2029 dataLen);
2030 break;
2035 return ret;
2038 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2039 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2040 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2042 BOOL ret = TRUE;
2043 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2044 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2045 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2046 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2048 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2049 pDecodePara, pvStructInfo, *pcbStructInfo);
2051 if (info)
2052 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2053 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2054 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2055 return ret;
2058 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2059 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2060 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2062 BOOL ret;
2064 __TRY
2066 struct AsnDecodeSequenceItem items[] = {
2067 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2068 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2069 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2070 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2071 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2072 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2073 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2074 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2075 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2076 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2077 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2080 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2081 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2082 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2084 __EXCEPT_PAGE_FAULT
2086 SetLastError(STATUS_ACCESS_VIOLATION);
2087 ret = FALSE;
2089 __ENDTRY
2090 return ret;
2093 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2094 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2095 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2097 BOOL ret = TRUE;
2099 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2100 pDecodePara, pvStructInfo, *pcbStructInfo);
2102 __TRY
2104 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2105 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2106 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2108 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2109 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2111 __EXCEPT_PAGE_FAULT
2113 SetLastError(STATUS_ACCESS_VIOLATION);
2114 ret = FALSE;
2116 __ENDTRY
2117 return ret;
2120 struct PATH_LEN_CONSTRAINT
2122 BOOL fPathLenConstraint;
2123 DWORD dwPathLenConstraint;
2126 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2127 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2128 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2130 BOOL ret = TRUE;
2132 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2133 pvStructInfo, *pcbStructInfo);
2135 if (cbEncoded)
2137 if (pbEncoded[0] == ASN_INTEGER)
2139 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2141 if (!pvStructInfo)
2142 *pcbStructInfo = bytesNeeded;
2143 else if (*pcbStructInfo < bytesNeeded)
2145 SetLastError(ERROR_MORE_DATA);
2146 *pcbStructInfo = bytesNeeded;
2147 ret = FALSE;
2149 else
2151 struct PATH_LEN_CONSTRAINT *constraint =
2152 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2153 DWORD size = sizeof(constraint->dwPathLenConstraint);
2155 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2156 pbEncoded, cbEncoded, 0, NULL,
2157 &constraint->dwPathLenConstraint, &size);
2158 if (ret)
2159 constraint->fPathLenConstraint = TRUE;
2160 TRACE("got an int, dwPathLenConstraint is %d\n",
2161 constraint->dwPathLenConstraint);
2164 else
2166 SetLastError(CRYPT_E_ASN1_CORRUPT);
2167 ret = FALSE;
2170 TRACE("returning %d (%08x)\n", ret, GetLastError());
2171 return ret;
2174 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2175 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2176 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2178 BOOL ret;
2179 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2180 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2181 offsetof(CERT_NAME_BLOB, pbData) };
2182 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2184 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2185 pDecodePara, pvStructInfo, *pcbStructInfo);
2187 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2188 pDecodePara, pvStructInfo, pcbStructInfo,
2189 entries ? entries->rgItems : NULL);
2190 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2191 return ret;
2194 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2195 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2196 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2198 BOOL ret;
2200 __TRY
2202 struct AsnDecodeSequenceItem items[] = {
2203 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2204 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2205 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2206 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2207 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2208 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2209 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2210 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2211 sizeof(struct GenericArray), TRUE, TRUE,
2212 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2215 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2216 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2217 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2219 __EXCEPT_PAGE_FAULT
2221 SetLastError(STATUS_ACCESS_VIOLATION);
2222 ret = FALSE;
2224 __ENDTRY
2225 return ret;
2228 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2229 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2230 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2232 BOOL ret;
2234 __TRY
2236 struct AsnDecodeSequenceItem items[] = {
2237 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2238 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2239 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2240 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2241 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2244 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2245 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2246 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2248 __EXCEPT_PAGE_FAULT
2250 SetLastError(STATUS_ACCESS_VIOLATION);
2251 ret = FALSE;
2253 __ENDTRY
2254 return ret;
2257 #define RSA1_MAGIC 0x31415352
2259 struct DECODED_RSA_PUB_KEY
2261 DWORD pubexp;
2262 CRYPT_INTEGER_BLOB modulus;
2265 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2266 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2267 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2269 BOOL ret;
2271 __TRY
2273 struct AsnDecodeSequenceItem items[] = {
2274 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2275 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2276 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2277 0 },
2278 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2279 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2281 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2282 DWORD size = 0;
2284 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2285 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2286 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2287 if (ret)
2289 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2290 decodedKey->modulus.cbData;
2292 if (!pvStructInfo)
2294 *pcbStructInfo = bytesNeeded;
2295 ret = TRUE;
2297 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2298 pvStructInfo, pcbStructInfo, bytesNeeded)))
2300 BLOBHEADER *hdr;
2301 RSAPUBKEY *rsaPubKey;
2303 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2304 pvStructInfo = *(BYTE **)pvStructInfo;
2305 hdr = (BLOBHEADER *)pvStructInfo;
2306 hdr->bType = PUBLICKEYBLOB;
2307 hdr->bVersion = CUR_BLOB_VERSION;
2308 hdr->reserved = 0;
2309 hdr->aiKeyAlg = CALG_RSA_KEYX;
2310 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2311 sizeof(BLOBHEADER));
2312 rsaPubKey->magic = RSA1_MAGIC;
2313 rsaPubKey->pubexp = decodedKey->pubexp;
2314 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2315 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2316 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2317 decodedKey->modulus.cbData);
2319 LocalFree(decodedKey);
2322 __EXCEPT_PAGE_FAULT
2324 SetLastError(STATUS_ACCESS_VIOLATION);
2325 ret = FALSE;
2327 __ENDTRY
2328 return ret;
2331 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2332 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2333 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2335 BOOL ret;
2336 DWORD bytesNeeded, dataLen;
2338 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2339 pDecodePara, pvStructInfo, *pcbStructInfo);
2341 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2343 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2344 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2345 else
2346 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2347 if (!pvStructInfo)
2348 *pcbStructInfo = bytesNeeded;
2349 else if (*pcbStructInfo < bytesNeeded)
2351 SetLastError(ERROR_MORE_DATA);
2352 *pcbStructInfo = bytesNeeded;
2353 ret = FALSE;
2355 else
2357 CRYPT_DATA_BLOB *blob;
2358 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2360 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2361 blob->cbData = dataLen;
2362 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2363 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2364 else
2366 assert(blob->pbData);
2367 if (blob->cbData)
2368 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2369 blob->cbData);
2373 return ret;
2376 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2377 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2378 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2380 BOOL ret;
2382 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2383 pDecodePara, pvStructInfo, *pcbStructInfo);
2385 __TRY
2387 DWORD bytesNeeded;
2389 if (!cbEncoded)
2391 SetLastError(CRYPT_E_ASN1_CORRUPT);
2392 ret = FALSE;
2394 else if (pbEncoded[0] != ASN_OCTETSTRING)
2396 SetLastError(CRYPT_E_ASN1_BADTAG);
2397 ret = FALSE;
2399 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2400 lpszStructType, pbEncoded, cbEncoded,
2401 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2403 if (!pvStructInfo)
2404 *pcbStructInfo = bytesNeeded;
2405 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2406 pvStructInfo, pcbStructInfo, bytesNeeded)))
2408 CRYPT_DATA_BLOB *blob;
2410 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2411 pvStructInfo = *(BYTE **)pvStructInfo;
2412 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2413 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2414 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2415 lpszStructType, pbEncoded, cbEncoded,
2416 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2417 &bytesNeeded);
2421 __EXCEPT_PAGE_FAULT
2423 SetLastError(STATUS_ACCESS_VIOLATION);
2424 ret = FALSE;
2426 __ENDTRY
2427 return ret;
2430 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2431 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2432 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2434 BOOL ret;
2436 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2437 pDecodePara, pvStructInfo, *pcbStructInfo);
2439 if (pbEncoded[0] == ASN_BITSTRING)
2441 DWORD bytesNeeded, dataLen;
2443 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2445 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2446 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2447 else
2448 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2449 if (!pvStructInfo)
2450 *pcbStructInfo = bytesNeeded;
2451 else if (*pcbStructInfo < bytesNeeded)
2453 *pcbStructInfo = bytesNeeded;
2454 SetLastError(ERROR_MORE_DATA);
2455 ret = FALSE;
2457 else
2459 CRYPT_BIT_BLOB *blob;
2461 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2462 blob->cbData = dataLen - 1;
2463 blob->cUnusedBits = *(pbEncoded + 1 +
2464 GET_LEN_BYTES(pbEncoded[1]));
2465 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2467 blob->pbData = (BYTE *)pbEncoded + 2 +
2468 GET_LEN_BYTES(pbEncoded[1]);
2470 else
2472 assert(blob->pbData);
2473 if (blob->cbData)
2475 BYTE mask = 0xff << blob->cUnusedBits;
2477 memcpy(blob->pbData, pbEncoded + 2 +
2478 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2479 blob->pbData[blob->cbData - 1] &= mask;
2485 else
2487 SetLastError(CRYPT_E_ASN1_BADTAG);
2488 ret = FALSE;
2490 TRACE("returning %d (%08x)\n", ret, GetLastError());
2491 return ret;
2494 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2495 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2496 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2498 BOOL ret;
2500 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2501 pDecodePara, pvStructInfo, pcbStructInfo);
2503 __TRY
2505 DWORD bytesNeeded;
2507 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2508 lpszStructType, pbEncoded, cbEncoded,
2509 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2511 if (!pvStructInfo)
2512 *pcbStructInfo = bytesNeeded;
2513 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2514 pvStructInfo, pcbStructInfo, bytesNeeded)))
2516 CRYPT_BIT_BLOB *blob;
2518 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2519 pvStructInfo = *(BYTE **)pvStructInfo;
2520 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2521 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2522 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2523 lpszStructType, pbEncoded, cbEncoded,
2524 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2525 &bytesNeeded);
2529 __EXCEPT_PAGE_FAULT
2531 SetLastError(STATUS_ACCESS_VIOLATION);
2532 ret = FALSE;
2534 __ENDTRY
2535 TRACE("returning %d (%08x)\n", ret, GetLastError());
2536 return ret;
2539 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2540 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2541 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2543 BOOL ret;
2545 if (!pvStructInfo)
2547 *pcbStructInfo = sizeof(int);
2548 return TRUE;
2550 __TRY
2552 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2553 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2554 DWORD size = sizeof(buf);
2556 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2557 if (pbEncoded[0] != ASN_INTEGER)
2559 SetLastError(CRYPT_E_ASN1_BADTAG);
2560 ret = FALSE;
2562 else
2563 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2564 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
2565 &size);
2566 if (ret)
2568 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2569 pvStructInfo, pcbStructInfo, sizeof(int))))
2571 int val, i;
2573 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2574 pvStructInfo = *(BYTE **)pvStructInfo;
2575 if (blob->pbData[blob->cbData - 1] & 0x80)
2577 /* initialize to a negative value to sign-extend */
2578 val = -1;
2580 else
2581 val = 0;
2582 for (i = 0; i < blob->cbData; i++)
2584 val <<= 8;
2585 val |= blob->pbData[blob->cbData - i - 1];
2587 memcpy(pvStructInfo, &val, sizeof(int));
2590 else if (GetLastError() == ERROR_MORE_DATA)
2591 SetLastError(CRYPT_E_ASN1_LARGE);
2593 __EXCEPT_PAGE_FAULT
2595 SetLastError(STATUS_ACCESS_VIOLATION);
2596 ret = FALSE;
2598 __ENDTRY
2599 return ret;
2602 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2603 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2604 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2606 BOOL ret;
2607 DWORD bytesNeeded, dataLen;
2609 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2611 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2613 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2614 if (!pvStructInfo)
2615 *pcbStructInfo = bytesNeeded;
2616 else if (*pcbStructInfo < bytesNeeded)
2618 *pcbStructInfo = bytesNeeded;
2619 SetLastError(ERROR_MORE_DATA);
2620 ret = FALSE;
2622 else
2624 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2626 blob->cbData = dataLen;
2627 assert(blob->pbData);
2628 if (blob->cbData)
2630 DWORD i;
2632 for (i = 0; i < blob->cbData; i++)
2634 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2635 dataLen - i - 1);
2640 return ret;
2643 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2644 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2645 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2647 BOOL ret;
2649 __TRY
2651 DWORD bytesNeeded;
2653 if (pbEncoded[0] != ASN_INTEGER)
2655 SetLastError(CRYPT_E_ASN1_BADTAG);
2656 ret = FALSE;
2658 else
2659 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2660 lpszStructType, pbEncoded, cbEncoded,
2661 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
2662 if (ret)
2664 if (!pvStructInfo)
2665 *pcbStructInfo = bytesNeeded;
2666 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2667 pvStructInfo, pcbStructInfo, bytesNeeded)))
2669 CRYPT_INTEGER_BLOB *blob;
2671 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2672 pvStructInfo = *(BYTE **)pvStructInfo;
2673 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2674 blob->pbData = (BYTE *)pvStructInfo +
2675 sizeof(CRYPT_INTEGER_BLOB);
2676 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2677 lpszStructType, pbEncoded, cbEncoded,
2678 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2679 &bytesNeeded);
2683 __EXCEPT_PAGE_FAULT
2685 SetLastError(STATUS_ACCESS_VIOLATION);
2686 ret = FALSE;
2688 __ENDTRY
2689 return ret;
2692 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
2693 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2694 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2695 void *pvStructInfo, DWORD *pcbStructInfo)
2697 BOOL ret;
2699 if (pbEncoded[0] == ASN_INTEGER)
2701 DWORD bytesNeeded, dataLen;
2703 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2705 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2707 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2708 if (!pvStructInfo)
2709 *pcbStructInfo = bytesNeeded;
2710 else if (*pcbStructInfo < bytesNeeded)
2712 *pcbStructInfo = bytesNeeded;
2713 SetLastError(ERROR_MORE_DATA);
2714 ret = FALSE;
2716 else
2718 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2720 blob->cbData = dataLen;
2721 assert(blob->pbData);
2722 /* remove leading zero byte if it exists */
2723 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2725 blob->cbData--;
2726 blob->pbData++;
2728 if (blob->cbData)
2730 DWORD i;
2732 for (i = 0; i < blob->cbData; i++)
2734 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2735 dataLen - i - 1);
2741 else
2743 SetLastError(CRYPT_E_ASN1_BADTAG);
2744 ret = FALSE;
2746 return ret;
2749 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2750 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2751 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2753 BOOL ret;
2755 __TRY
2757 DWORD bytesNeeded;
2759 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2760 lpszStructType, pbEncoded, cbEncoded,
2761 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2763 if (!pvStructInfo)
2764 *pcbStructInfo = bytesNeeded;
2765 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2766 pvStructInfo, pcbStructInfo, bytesNeeded)))
2768 CRYPT_INTEGER_BLOB *blob;
2770 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2771 pvStructInfo = *(BYTE **)pvStructInfo;
2772 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2773 blob->pbData = (BYTE *)pvStructInfo +
2774 sizeof(CRYPT_INTEGER_BLOB);
2775 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2776 lpszStructType, pbEncoded, cbEncoded,
2777 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2778 &bytesNeeded);
2782 __EXCEPT_PAGE_FAULT
2784 SetLastError(STATUS_ACCESS_VIOLATION);
2785 ret = FALSE;
2787 __ENDTRY
2788 return ret;
2791 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
2792 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2793 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2795 BOOL ret;
2797 if (!pvStructInfo)
2799 *pcbStructInfo = sizeof(int);
2800 return TRUE;
2802 __TRY
2804 if (pbEncoded[0] == ASN_ENUMERATED)
2806 unsigned int val = 0, i;
2808 if (cbEncoded <= 1)
2810 SetLastError(CRYPT_E_ASN1_EOD);
2811 ret = FALSE;
2813 else if (pbEncoded[1] == 0)
2815 SetLastError(CRYPT_E_ASN1_CORRUPT);
2816 ret = FALSE;
2818 else
2820 /* A little strange looking, but we have to accept a sign byte:
2821 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
2822 * assuming a small length is okay here, it has to be in short
2823 * form.
2825 if (pbEncoded[1] > sizeof(unsigned int) + 1)
2827 SetLastError(CRYPT_E_ASN1_LARGE);
2828 return FALSE;
2830 for (i = 0; i < pbEncoded[1]; i++)
2832 val <<= 8;
2833 val |= pbEncoded[2 + i];
2835 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2836 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
2838 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2839 pvStructInfo = *(BYTE **)pvStructInfo;
2840 memcpy(pvStructInfo, &val, sizeof(unsigned int));
2844 else
2846 SetLastError(CRYPT_E_ASN1_BADTAG);
2847 ret = FALSE;
2850 __EXCEPT_PAGE_FAULT
2852 SetLastError(STATUS_ACCESS_VIOLATION);
2853 ret = FALSE;
2855 __ENDTRY
2856 return ret;
2859 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
2860 * if it fails.
2862 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
2863 do { \
2864 BYTE i; \
2866 (word) = 0; \
2867 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
2869 if (!isdigit(*(pbEncoded))) \
2871 SetLastError(CRYPT_E_ASN1_CORRUPT); \
2872 ret = FALSE; \
2874 else \
2876 (word) *= 10; \
2877 (word) += *(pbEncoded)++ - '0'; \
2880 } while (0)
2882 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
2883 SYSTEMTIME *sysTime)
2885 BOOL ret;
2887 __TRY
2889 ret = TRUE;
2890 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
2892 WORD hours, minutes = 0;
2893 BYTE sign = *pbEncoded++;
2895 len--;
2896 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
2897 if (ret && hours >= 24)
2899 SetLastError(CRYPT_E_ASN1_CORRUPT);
2900 ret = FALSE;
2902 else if (len >= 2)
2904 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
2905 if (ret && minutes >= 60)
2907 SetLastError(CRYPT_E_ASN1_CORRUPT);
2908 ret = FALSE;
2911 if (ret)
2913 if (sign == '+')
2915 sysTime->wHour += hours;
2916 sysTime->wMinute += minutes;
2918 else
2920 if (hours > sysTime->wHour)
2922 sysTime->wDay--;
2923 sysTime->wHour = 24 - (hours - sysTime->wHour);
2925 else
2926 sysTime->wHour -= hours;
2927 if (minutes > sysTime->wMinute)
2929 sysTime->wHour--;
2930 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
2932 else
2933 sysTime->wMinute -= minutes;
2938 __EXCEPT_PAGE_FAULT
2940 SetLastError(STATUS_ACCESS_VIOLATION);
2941 ret = FALSE;
2943 __ENDTRY
2944 return ret;
2947 #define MIN_ENCODED_TIME_LENGTH 10
2949 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
2950 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2951 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2953 BOOL ret;
2955 if (!pvStructInfo)
2957 *pcbStructInfo = sizeof(FILETIME);
2958 return TRUE;
2960 __TRY
2962 ret = TRUE;
2963 if (pbEncoded[0] == ASN_UTCTIME)
2965 if (cbEncoded <= 1)
2967 SetLastError(CRYPT_E_ASN1_EOD);
2968 ret = FALSE;
2970 else if (pbEncoded[1] > 0x7f)
2972 /* long-form date strings really can't be valid */
2973 SetLastError(CRYPT_E_ASN1_CORRUPT);
2974 ret = FALSE;
2976 else
2978 SYSTEMTIME sysTime = { 0 };
2979 BYTE len = pbEncoded[1];
2981 if (len < MIN_ENCODED_TIME_LENGTH)
2983 SetLastError(CRYPT_E_ASN1_CORRUPT);
2984 ret = FALSE;
2986 else
2988 pbEncoded += 2;
2989 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
2990 if (sysTime.wYear >= 50)
2991 sysTime.wYear += 1900;
2992 else
2993 sysTime.wYear += 2000;
2994 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2995 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2996 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2997 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
2998 if (ret && len > 0)
3000 if (len >= 2 && isdigit(*pbEncoded) &&
3001 isdigit(*(pbEncoded + 1)))
3002 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3003 sysTime.wSecond);
3004 else if (isdigit(*pbEncoded))
3005 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3006 sysTime.wSecond);
3007 if (ret)
3008 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3009 &sysTime);
3011 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3012 pDecodePara, pvStructInfo, pcbStructInfo,
3013 sizeof(FILETIME))))
3015 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3016 pvStructInfo = *(BYTE **)pvStructInfo;
3017 ret = SystemTimeToFileTime(&sysTime,
3018 (FILETIME *)pvStructInfo);
3023 else
3025 SetLastError(CRYPT_E_ASN1_BADTAG);
3026 ret = FALSE;
3029 __EXCEPT_PAGE_FAULT
3031 SetLastError(STATUS_ACCESS_VIOLATION);
3032 ret = FALSE;
3034 __ENDTRY
3035 return ret;
3038 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3039 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3040 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3042 BOOL ret;
3044 if (!pvStructInfo)
3046 *pcbStructInfo = sizeof(FILETIME);
3047 return TRUE;
3049 __TRY
3051 ret = TRUE;
3052 if (pbEncoded[0] == ASN_GENERALTIME)
3054 if (cbEncoded <= 1)
3056 SetLastError(CRYPT_E_ASN1_EOD);
3057 ret = FALSE;
3059 else if (pbEncoded[1] > 0x7f)
3061 /* long-form date strings really can't be valid */
3062 SetLastError(CRYPT_E_ASN1_CORRUPT);
3063 ret = FALSE;
3065 else
3067 BYTE len = pbEncoded[1];
3069 if (len < MIN_ENCODED_TIME_LENGTH)
3071 SetLastError(CRYPT_E_ASN1_CORRUPT);
3072 ret = FALSE;
3074 else
3076 SYSTEMTIME sysTime = { 0 };
3078 pbEncoded += 2;
3079 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3080 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3081 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3082 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3083 if (ret && len > 0)
3085 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3086 sysTime.wMinute);
3087 if (ret && len > 0)
3088 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3089 sysTime.wSecond);
3090 if (ret && len > 0 && (*pbEncoded == '.' ||
3091 *pbEncoded == ','))
3093 BYTE digits;
3095 pbEncoded++;
3096 len--;
3097 /* workaround macro weirdness */
3098 digits = min(len, 3);
3099 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3100 sysTime.wMilliseconds);
3102 if (ret)
3103 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3104 &sysTime);
3106 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3107 pDecodePara, pvStructInfo, pcbStructInfo,
3108 sizeof(FILETIME))))
3110 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3111 pvStructInfo = *(BYTE **)pvStructInfo;
3112 ret = SystemTimeToFileTime(&sysTime,
3113 (FILETIME *)pvStructInfo);
3118 else
3120 SetLastError(CRYPT_E_ASN1_BADTAG);
3121 ret = FALSE;
3124 __EXCEPT_PAGE_FAULT
3126 SetLastError(STATUS_ACCESS_VIOLATION);
3127 ret = FALSE;
3129 __ENDTRY
3130 return ret;
3133 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3134 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3135 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3137 BOOL ret;
3139 __TRY
3141 if (pbEncoded[0] == ASN_UTCTIME)
3142 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3143 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3144 pcbStructInfo);
3145 else if (pbEncoded[0] == ASN_GENERALTIME)
3146 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3147 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3148 pvStructInfo, pcbStructInfo);
3149 else
3151 SetLastError(CRYPT_E_ASN1_BADTAG);
3152 ret = FALSE;
3155 __EXCEPT_PAGE_FAULT
3157 SetLastError(STATUS_ACCESS_VIOLATION);
3158 ret = FALSE;
3160 __ENDTRY
3161 return ret;
3164 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3165 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3166 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3168 BOOL ret = TRUE;
3170 __TRY
3172 if (pbEncoded[0] == ASN_SEQUENCEOF)
3174 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3176 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3178 BYTE lenBytes;
3179 const BYTE *ptr;
3181 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3182 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3183 cValue = 0;
3184 ptr = pbEncoded + 1 + lenBytes;
3185 remainingLen = dataLen;
3186 while (ret && remainingLen)
3188 DWORD nextLen;
3190 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3191 if (ret)
3193 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3195 remainingLen -= 1 + nextLenBytes + nextLen;
3196 ptr += 1 + nextLenBytes + nextLen;
3197 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3198 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3199 bytesNeeded += 1 + nextLenBytes + nextLen;
3200 cValue++;
3203 if (ret)
3205 CRYPT_SEQUENCE_OF_ANY *seq;
3206 BYTE *nextPtr;
3207 DWORD i;
3209 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3210 pvStructInfo, pcbStructInfo, bytesNeeded)))
3212 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3213 pvStructInfo = *(BYTE **)pvStructInfo;
3214 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3215 seq->cValue = cValue;
3216 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3217 sizeof(*seq));
3218 nextPtr = (BYTE *)seq->rgValue +
3219 cValue * sizeof(CRYPT_DER_BLOB);
3220 ptr = pbEncoded + 1 + lenBytes;
3221 remainingLen = dataLen;
3222 i = 0;
3223 while (ret && remainingLen)
3225 DWORD nextLen;
3227 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3228 if (ret)
3230 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3232 seq->rgValue[i].cbData = 1 + nextLenBytes +
3233 nextLen;
3234 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3235 seq->rgValue[i].pbData = (BYTE *)ptr;
3236 else
3238 seq->rgValue[i].pbData = nextPtr;
3239 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3240 nextLen);
3241 nextPtr += 1 + nextLenBytes + nextLen;
3243 remainingLen -= 1 + nextLenBytes + nextLen;
3244 ptr += 1 + nextLenBytes + nextLen;
3245 i++;
3252 else
3254 SetLastError(CRYPT_E_ASN1_BADTAG);
3255 ret = FALSE;
3258 __EXCEPT_PAGE_FAULT
3260 SetLastError(STATUS_ACCESS_VIOLATION);
3261 ret = FALSE;
3263 __ENDTRY
3264 return ret;
3267 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3268 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3269 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3271 BOOL ret;
3273 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3275 DWORD bytesNeeded, dataLen;
3277 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3279 struct AsnArrayDescriptor arrayDesc = {
3280 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3281 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3282 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3283 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3285 if (dataLen)
3287 DWORD nameLen;
3289 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3290 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3291 0, NULL, NULL, &nameLen, NULL);
3292 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3294 else
3295 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3296 if (!pvStructInfo)
3297 *pcbStructInfo = bytesNeeded;
3298 else if (*pcbStructInfo < bytesNeeded)
3300 *pcbStructInfo = bytesNeeded;
3301 SetLastError(ERROR_MORE_DATA);
3302 ret = FALSE;
3304 else
3306 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3308 if (dataLen)
3310 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3311 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3312 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3313 0, NULL, &name->u.FullName, pcbStructInfo,
3314 name->u.FullName.rgAltEntry);
3316 else
3317 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3321 else
3323 SetLastError(CRYPT_E_ASN1_BADTAG);
3324 ret = FALSE;
3326 return ret;
3329 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3330 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3331 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3333 struct AsnDecodeSequenceItem items[] = {
3334 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3335 DistPointName), CRYPT_AsnDecodeDistPointName,
3336 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3337 DistPointName.u.FullName.rgAltEntry), 0 },
3338 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3339 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3340 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3341 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3342 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3343 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3345 BOOL ret;
3347 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3348 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3349 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3350 return ret;
3353 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3354 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3355 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3357 BOOL ret;
3359 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3360 pDecodePara, pvStructInfo, *pcbStructInfo);
3362 __TRY
3364 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3365 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3366 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3368 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3369 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3371 __EXCEPT_PAGE_FAULT
3373 SetLastError(STATUS_ACCESS_VIOLATION);
3374 ret = FALSE;
3376 __ENDTRY
3377 return ret;
3380 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3381 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3382 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3384 BOOL ret;
3386 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3387 pDecodePara, pvStructInfo, *pcbStructInfo);
3389 __TRY
3391 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3392 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3394 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3395 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3397 __EXCEPT_PAGE_FAULT
3399 SetLastError(STATUS_ACCESS_VIOLATION);
3400 ret = FALSE;
3402 __ENDTRY
3403 return ret;
3406 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3407 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3408 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3410 BOOL ret;
3412 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3413 pDecodePara, pvStructInfo, *pcbStructInfo);
3415 __TRY
3417 struct AsnDecodeSequenceItem items[] = {
3418 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3419 DistPointName), CRYPT_AsnDecodeDistPointName,
3420 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3421 offsetof(CRL_ISSUING_DIST_POINT,
3422 DistPointName.u.FullName.rgAltEntry), 0 },
3423 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3424 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3425 FALSE, 0 },
3426 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3427 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3428 FALSE, 0 },
3429 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3430 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3431 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3432 OnlySomeReasonFlags.pbData), 0 },
3433 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3434 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3437 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3438 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3439 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3441 __EXCEPT_PAGE_FAULT
3443 SetLastError(STATUS_ACCESS_VIOLATION);
3444 ret = FALSE;
3446 __ENDTRY
3447 return ret;
3450 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3451 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3452 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3454 static HCRYPTOIDFUNCSET set = NULL;
3455 BOOL ret = FALSE;
3456 CryptDecodeObjectExFunc decodeFunc = NULL;
3457 HCRYPTOIDFUNCADDR hFunc = NULL;
3459 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
3460 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
3461 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3463 if (!pvStructInfo && !pcbStructInfo)
3465 SetLastError(ERROR_INVALID_PARAMETER);
3466 return FALSE;
3468 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3469 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3471 SetLastError(ERROR_FILE_NOT_FOUND);
3472 return FALSE;
3474 if (!cbEncoded)
3476 SetLastError(CRYPT_E_ASN1_EOD);
3477 return FALSE;
3479 if (cbEncoded > MAX_ENCODED_LEN)
3481 SetLastError(CRYPT_E_ASN1_LARGE);
3482 return FALSE;
3485 SetLastError(NOERROR);
3486 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3487 *(BYTE **)pvStructInfo = NULL;
3488 if (!HIWORD(lpszStructType))
3490 switch (LOWORD(lpszStructType))
3492 case (WORD)X509_CERT:
3493 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3494 break;
3495 case (WORD)X509_CERT_TO_BE_SIGNED:
3496 decodeFunc = CRYPT_AsnDecodeCert;
3497 break;
3498 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3499 decodeFunc = CRYPT_AsnDecodeCRL;
3500 break;
3501 case (WORD)X509_EXTENSIONS:
3502 decodeFunc = CRYPT_AsnDecodeExtensions;
3503 break;
3504 case (WORD)X509_NAME_VALUE:
3505 decodeFunc = CRYPT_AsnDecodeNameValue;
3506 break;
3507 case (WORD)X509_NAME:
3508 decodeFunc = CRYPT_AsnDecodeName;
3509 break;
3510 case (WORD)X509_PUBLIC_KEY_INFO:
3511 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
3512 break;
3513 case (WORD)X509_AUTHORITY_KEY_ID:
3514 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3515 break;
3516 case (WORD)X509_ALTERNATE_NAME:
3517 decodeFunc = CRYPT_AsnDecodeAltName;
3518 break;
3519 case (WORD)X509_BASIC_CONSTRAINTS:
3520 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3521 break;
3522 case (WORD)X509_BASIC_CONSTRAINTS2:
3523 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3524 break;
3525 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3526 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3527 break;
3528 case (WORD)X509_UNICODE_NAME:
3529 decodeFunc = CRYPT_AsnDecodeUnicodeName;
3530 break;
3531 case (WORD)X509_UNICODE_NAME_VALUE:
3532 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
3533 break;
3534 case (WORD)X509_OCTET_STRING:
3535 decodeFunc = CRYPT_AsnDecodeOctets;
3536 break;
3537 case (WORD)X509_BITS:
3538 case (WORD)X509_KEY_USAGE:
3539 decodeFunc = CRYPT_AsnDecodeBits;
3540 break;
3541 case (WORD)X509_INTEGER:
3542 decodeFunc = CRYPT_AsnDecodeInt;
3543 break;
3544 case (WORD)X509_MULTI_BYTE_INTEGER:
3545 decodeFunc = CRYPT_AsnDecodeInteger;
3546 break;
3547 case (WORD)X509_MULTI_BYTE_UINT:
3548 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3549 break;
3550 case (WORD)X509_ENUMERATED:
3551 decodeFunc = CRYPT_AsnDecodeEnumerated;
3552 break;
3553 case (WORD)X509_CHOICE_OF_TIME:
3554 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3555 break;
3556 case (WORD)X509_SEQUENCE_OF_ANY:
3557 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3558 break;
3559 case (WORD)PKCS_UTC_TIME:
3560 decodeFunc = CRYPT_AsnDecodeUtcTime;
3561 break;
3562 case (WORD)X509_CRL_DIST_POINTS:
3563 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3564 break;
3565 case (WORD)X509_ENHANCED_KEY_USAGE:
3566 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3567 break;
3568 case (WORD)X509_ISSUING_DIST_POINT:
3569 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3570 break;
3571 default:
3572 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3575 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3576 decodeFunc = CRYPT_AsnDecodeExtensions;
3577 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3578 decodeFunc = CRYPT_AsnDecodeUtcTime;
3579 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3580 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3581 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3582 decodeFunc = CRYPT_AsnDecodeEnumerated;
3583 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3584 decodeFunc = CRYPT_AsnDecodeBits;
3585 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3586 decodeFunc = CRYPT_AsnDecodeOctets;
3587 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3588 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3589 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3590 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3591 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3592 decodeFunc = CRYPT_AsnDecodeAltName;
3593 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3594 decodeFunc = CRYPT_AsnDecodeAltName;
3595 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3596 decodeFunc = CRYPT_AsnDecodeAltName;
3597 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3598 decodeFunc = CRYPT_AsnDecodeAltName;
3599 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3600 decodeFunc = CRYPT_AsnDecodeAltName;
3601 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3602 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3603 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3604 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3605 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3606 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3607 else
3608 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3609 debugstr_a(lpszStructType));
3610 if (!decodeFunc)
3612 if (!set)
3613 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
3614 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3615 (void **)&decodeFunc, &hFunc);
3617 if (decodeFunc)
3618 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3619 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3620 else
3621 SetLastError(ERROR_FILE_NOT_FOUND);
3622 if (hFunc)
3623 CryptFreeOIDFunctionAddress(hFunc, 0);
3624 return ret;