wined3d: Cleanup device_map_fixed_function_samplers().
[wine/gsoc_dplay.git] / dlls / crypt32 / decode.c
blobd3f3322b6771c5d4af2e86b439102642630bd5bf
1 /*
2 * Copyright 2005 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface is
21 * undocumented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially:
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
34 #include <assert.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
39 #define NONAMELESSUNION
41 #include "windef.h"
42 #include "winbase.h"
43 #include "wincrypt.h"
44 #include "winnls.h"
45 #include "snmp.h"
46 #include "wine/debug.h"
47 #include "wine/exception.h"
48 #include "crypt32_private.h"
50 /* This is a bit arbitrary, but to set some limit: */
51 #define MAX_ENCODED_LEN 0x02000000
53 #define ASN_FLAGS_MASK 0xe0
54 #define ASN_TYPE_MASK 0x1f
56 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
58 struct GenericArray
60 DWORD cItems;
61 BYTE *rgItems;
64 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
65 DWORD, DWORD, void *, DWORD *);
66 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
67 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
69 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
70 * The dwCertEncodingType and lpszStructType are ignored by the built-in
71 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
72 * since it must call functions in external DLLs that follow these signatures.
74 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
75 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
76 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
77 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
78 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
79 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
80 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
81 * time, doesn't do memory allocation, and doesn't do exception handling.
82 * (This isn't intended to be the externally-called one.)
84 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
86 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
87 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
88 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
89 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
90 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
91 /* Internal function */
92 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
93 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
94 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
97 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
98 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
99 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
100 * member has been initialized, doesn't do exception handling, and doesn't do
101 * memory allocation.
103 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
104 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
105 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
106 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
107 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
108 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
109 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
110 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
111 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
112 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
113 * member has been initialized, doesn't do exception handling, and doesn't do
114 * memory allocation. Also doesn't check tag, assumes the caller has checked
115 * it.
117 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
118 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
119 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
120 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
121 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
122 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
123 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
124 void *pvStructInfo, DWORD *pcbStructInfo);
126 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
127 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
128 DWORD *pcbStructInfo)
130 static HCRYPTOIDFUNCSET set = NULL;
131 BOOL ret = FALSE;
132 CryptDecodeObjectFunc pCryptDecodeObject;
133 HCRYPTOIDFUNCADDR hFunc;
135 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
136 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
137 pvStructInfo, pcbStructInfo);
139 if (!pvStructInfo && !pcbStructInfo)
141 SetLastError(ERROR_INVALID_PARAMETER);
142 return FALSE;
145 /* Try registered DLL first.. */
146 if (!set)
147 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
148 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
149 (void **)&pCryptDecodeObject, &hFunc);
150 if (pCryptDecodeObject)
152 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
153 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
154 CryptFreeOIDFunctionAddress(hFunc, 0);
156 else
158 /* If not, use CryptDecodeObjectEx */
159 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
160 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
162 return ret;
165 /* Gets the number of length bytes from the given (leading) length byte */
166 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
168 /* Helper function to get the encoded length of the data starting at pbEncoded,
169 * where pbEncoded[0] is the tag. If the data are too short to contain a
170 * length or if the length is too large for cbEncoded, sets an appropriate
171 * error code and returns FALSE.
173 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
174 DWORD *len)
176 BOOL ret;
178 if (cbEncoded <= 1)
180 SetLastError(CRYPT_E_ASN1_CORRUPT);
181 ret = FALSE;
183 else if (pbEncoded[1] <= 0x7f)
185 if (pbEncoded[1] + 1 > cbEncoded)
187 SetLastError(CRYPT_E_ASN1_EOD);
188 ret = FALSE;
190 else
192 *len = pbEncoded[1];
193 ret = TRUE;
196 else
198 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
200 if (lenLen > sizeof(DWORD) + 1)
202 SetLastError(CRYPT_E_ASN1_LARGE);
203 ret = FALSE;
205 else if (lenLen + 2 > cbEncoded)
207 SetLastError(CRYPT_E_ASN1_CORRUPT);
208 ret = FALSE;
210 else
212 DWORD out = 0;
214 pbEncoded += 2;
215 while (--lenLen)
217 out <<= 8;
218 out |= *pbEncoded++;
220 if (out + lenLen + 1 > cbEncoded)
222 SetLastError(CRYPT_E_ASN1_EOD);
223 ret = FALSE;
225 else
227 *len = out;
228 ret = TRUE;
232 return ret;
235 /* Helper function to check *pcbStructInfo, set it to the required size, and
236 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
237 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
238 * pointer to the newly allocated memory.
240 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
241 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
242 DWORD bytesNeeded)
244 BOOL ret = TRUE;
246 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
248 if (pDecodePara && pDecodePara->pfnAlloc)
249 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
250 else
251 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
252 if (!*(BYTE **)pvStructInfo)
253 ret = FALSE;
254 else
255 *pcbStructInfo = bytesNeeded;
257 else if (*pcbStructInfo < bytesNeeded)
259 *pcbStructInfo = bytesNeeded;
260 SetLastError(ERROR_MORE_DATA);
261 ret = FALSE;
263 return ret;
266 /* tag:
267 * The expected tag of the item. If tag is 0, decodeFunc is called
268 * regardless of the tag value seen.
269 * offset:
270 * A sequence is decoded into a struct. The offset member is the
271 * offset of this item within that struct.
272 * decodeFunc:
273 * The decoder function to use. If this is NULL, then the member isn't
274 * decoded, but minSize space is reserved for it.
275 * minSize:
276 * The minimum amount of space occupied after decoding. You must set this.
277 * optional:
278 * If true, and the tag doesn't match the expected tag for this item,
279 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
280 * filled with 0 for this member.
281 * hasPointer, pointerOffset, minSize:
282 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
283 * the offset within the (outer) struct of the data pointer (or to the
284 * first data pointer, if more than one exist).
285 * size:
286 * Used by CRYPT_AsnDecodeSequence, not for your use.
288 struct AsnDecodeSequenceItem
290 BYTE tag;
291 DWORD offset;
292 CryptDecodeObjectExFunc decodeFunc;
293 DWORD minSize;
294 BOOL optional;
295 BOOL hasPointer;
296 DWORD pointerOffset;
297 DWORD size;
300 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
301 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
302 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData)
304 BOOL ret;
305 DWORD i;
306 const BYTE *ptr;
308 ptr = pbEncoded + 1 + GET_LEN_BYTES(pbEncoded[1]);
309 for (i = 0, ret = TRUE; ret && i < cItem; i++)
311 if (cbEncoded - (ptr - pbEncoded) != 0)
313 DWORD nextItemLen;
315 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
316 &nextItemLen)))
318 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
320 if (ptr[0] == items[i].tag || !items[i].tag)
322 if (nextData && pvStructInfo && items[i].hasPointer)
324 TRACE("Setting next pointer to %p\n",
325 nextData);
326 *(BYTE **)((BYTE *)pvStructInfo +
327 items[i].pointerOffset) = nextData;
329 if (items[i].decodeFunc)
331 if (pvStructInfo)
332 TRACE("decoding item %d\n", i);
333 else
334 TRACE("sizing item %d\n", i);
335 ret = items[i].decodeFunc(dwCertEncodingType,
336 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
337 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
338 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
339 : NULL, &items[i].size);
340 if (ret)
342 if (nextData && items[i].hasPointer &&
343 items[i].size > items[i].minSize)
345 nextData += items[i].size - items[i].minSize;
346 /* align nextData to DWORD boundaries */
347 if (items[i].size % sizeof(DWORD))
348 nextData += sizeof(DWORD) - items[i].size %
349 sizeof(DWORD);
351 /* Account for alignment padding */
352 if (items[i].size % sizeof(DWORD))
353 items[i].size += sizeof(DWORD) -
354 items[i].size % sizeof(DWORD);
355 ptr += 1 + nextItemLenBytes + nextItemLen;
357 else if (items[i].optional &&
358 GetLastError() == CRYPT_E_ASN1_BADTAG)
360 TRACE("skipping optional item %d\n", i);
361 items[i].size = items[i].minSize;
362 SetLastError(NOERROR);
363 ret = TRUE;
365 else
366 TRACE("item %d failed: %08x\n", i,
367 GetLastError());
369 else
370 items[i].size = items[i].minSize;
372 else if (items[i].optional)
374 TRACE("skipping optional item %d\n", i);
375 items[i].size = items[i].minSize;
377 else
379 TRACE("tag %02x doesn't match expected %02x\n",
380 ptr[0], items[i].tag);
381 SetLastError(CRYPT_E_ASN1_BADTAG);
382 ret = FALSE;
386 else if (items[i].optional)
388 TRACE("missing optional item %d, skipping\n", i);
389 items[i].size = items[i].minSize;
391 else
393 TRACE("not enough bytes for item %d, failing\n", i);
394 SetLastError(CRYPT_E_ASN1_CORRUPT);
395 ret = FALSE;
398 if (cbEncoded - (ptr - pbEncoded) != 0)
400 TRACE("%d remaining bytes, failing\n", cbEncoded -
401 (ptr - pbEncoded));
402 SetLastError(CRYPT_E_ASN1_CORRUPT);
403 ret = FALSE;
405 return ret;
408 /* This decodes an arbitrary sequence into a contiguous block of memory
409 * (basically, a struct.) Each element being decoded is described by a struct
410 * AsnDecodeSequenceItem, see above.
411 * startingPointer is an optional pointer to the first place where dynamic
412 * data will be stored. If you know the starting offset, you may pass it
413 * here. Otherwise, pass NULL, and one will be inferred from the items.
414 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
415 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
417 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
418 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
419 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
420 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
422 BOOL ret;
424 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
425 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
426 startingPointer);
428 if (pbEncoded[0] == ASN_SEQUENCE)
430 DWORD dataLen;
432 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
434 DWORD i;
436 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
437 cbEncoded, dwFlags, NULL, NULL);
438 if (ret)
440 DWORD bytesNeeded = 0, structSize = 0;
442 for (i = 0; i < cItem; i++)
444 bytesNeeded += items[i].size;
445 structSize += items[i].minSize;
447 if (!pvStructInfo)
448 *pcbStructInfo = bytesNeeded;
449 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
450 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
452 BYTE *nextData;
454 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
455 pvStructInfo = *(BYTE **)pvStructInfo;
456 if (startingPointer)
457 nextData = (BYTE *)startingPointer;
458 else
459 nextData = (BYTE *)pvStructInfo + structSize;
460 memset(pvStructInfo, 0, structSize);
461 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
462 pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
467 else
469 SetLastError(CRYPT_E_ASN1_BADTAG);
470 ret = FALSE;
472 TRACE("returning %d (%08x)\n", ret, GetLastError());
473 return ret;
476 /* tag:
477 * The expected tag of the entire encoded array (usually a variant
478 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
479 * regardless of the tag seen.
480 * decodeFunc:
481 * used to decode each item in the array
482 * itemSize:
483 * is the minimum size of each decoded item
484 * hasPointer:
485 * indicates whether each item has a dynamic pointer
486 * pointerOffset:
487 * indicates the offset within itemSize at which the pointer exists
489 struct AsnArrayDescriptor
491 BYTE tag;
492 CryptDecodeObjectExFunc decodeFunc;
493 DWORD itemSize;
494 BOOL hasPointer;
495 DWORD pointerOffset;
498 struct AsnArrayItemSize
500 DWORD encodedLen;
501 DWORD size;
504 /* Decodes an array of like types into a struct GenericArray.
505 * The layout and decoding of the array are described by a struct
506 * AsnArrayDescriptor.
508 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
509 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
510 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
511 void *startingPointer)
513 BOOL ret = TRUE;
515 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
516 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
517 startingPointer);
519 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
521 DWORD dataLen;
523 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
525 DWORD bytesNeeded, cItems = 0;
526 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
527 /* There can be arbitrarily many items, but there is often only one.
529 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
531 bytesNeeded = sizeof(struct GenericArray);
532 if (dataLen)
534 const BYTE *ptr;
536 for (ptr = pbEncoded + 1 + lenBytes; ret &&
537 ptr - pbEncoded - 1 - lenBytes < dataLen; )
539 DWORD itemLenBytes, itemDataLen, size = 0;
541 itemLenBytes = GET_LEN_BYTES(ptr[1]);
542 /* Each item decoded may not tolerate extraneous bytes, so
543 * get the length of the next element and pass it directly.
545 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
546 &itemDataLen);
547 if (ret)
548 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
549 1 + itemLenBytes + itemDataLen,
550 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
551 &size);
552 if (ret)
554 DWORD nextLen;
556 cItems++;
557 if (itemSizes != &itemSize)
558 itemSizes = CryptMemRealloc(itemSizes,
559 cItems * sizeof(struct AsnArrayItemSize));
560 else
562 itemSizes =
563 CryptMemAlloc(
564 cItems * sizeof(struct AsnArrayItemSize));
565 if (itemSizes)
566 memcpy(itemSizes, &itemSize, sizeof(itemSize));
568 if (itemSizes)
570 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
571 + itemDataLen;
572 itemSizes[cItems - 1].size = size;
573 bytesNeeded += size;
574 ret = CRYPT_GetLen(ptr,
575 cbEncoded - (ptr - pbEncoded), &nextLen);
576 if (ret)
577 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
579 else
580 ret = FALSE;
584 if (ret)
586 if (!pvStructInfo)
587 *pcbStructInfo = bytesNeeded;
588 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
589 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
591 DWORD i;
592 BYTE *nextData;
593 const BYTE *ptr;
594 struct GenericArray *array;
596 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
597 pvStructInfo = *(BYTE **)pvStructInfo;
598 array = (struct GenericArray *)pvStructInfo;
599 array->cItems = cItems;
600 if (startingPointer)
601 array->rgItems = startingPointer;
602 else
603 array->rgItems = (BYTE *)array +
604 sizeof(struct GenericArray);
605 nextData = (BYTE *)array->rgItems +
606 array->cItems * arrayDesc->itemSize;
607 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
608 i < cItems && ptr - pbEncoded - 1 - lenBytes <
609 dataLen; i++)
611 if (arrayDesc->hasPointer)
612 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
613 + arrayDesc->pointerOffset) = nextData;
614 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
615 itemSizes[i].encodedLen,
616 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
617 array->rgItems + i * arrayDesc->itemSize,
618 &itemSizes[i].size);
619 if (ret)
621 DWORD nextLen;
623 nextData += itemSizes[i].size - arrayDesc->itemSize;
624 ret = CRYPT_GetLen(ptr,
625 cbEncoded - (ptr - pbEncoded), &nextLen);
626 if (ret)
627 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
632 if (itemSizes != &itemSize)
633 CryptMemFree(itemSizes);
636 else
638 SetLastError(CRYPT_E_ASN1_BADTAG);
639 ret = FALSE;
641 return ret;
644 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
645 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
646 * to CRYPT_E_ASN1_CORRUPT.
647 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
648 * set!
650 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
651 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
652 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
654 BOOL ret;
655 DWORD dataLen;
657 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
659 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
660 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
662 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
663 bytesNeeded += 1 + lenBytes + dataLen;
665 if (!pvStructInfo)
666 *pcbStructInfo = bytesNeeded;
667 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
668 pvStructInfo, pcbStructInfo, bytesNeeded)))
670 CRYPT_DER_BLOB *blob;
672 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
673 pvStructInfo = *(BYTE **)pvStructInfo;
674 blob = (CRYPT_DER_BLOB *)pvStructInfo;
675 blob->cbData = 1 + lenBytes + dataLen;
676 if (blob->cbData)
678 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
679 blob->pbData = (BYTE *)pbEncoded;
680 else
682 assert(blob->pbData);
683 memcpy(blob->pbData, pbEncoded, blob->cbData);
686 else
688 SetLastError(CRYPT_E_ASN1_CORRUPT);
689 ret = FALSE;
693 return ret;
696 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
697 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
698 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
699 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
701 BOOL ret;
703 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
704 pDecodePara, pvStructInfo, *pcbStructInfo);
706 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
707 * place.
709 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
710 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
711 pvStructInfo, pcbStructInfo);
712 if (ret && pvStructInfo)
714 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
716 if (blob->cbData)
718 DWORD i;
719 BYTE temp;
721 for (i = 0; i < blob->cbData / 2; i++)
723 temp = blob->pbData[i];
724 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
725 blob->pbData[blob->cbData - i - 1] = temp;
729 TRACE("returning %d (%08x)\n", ret, GetLastError());
730 return ret;
733 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
734 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
735 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
737 BOOL ret = TRUE;
739 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
740 pDecodePara, pvStructInfo, *pcbStructInfo);
742 __TRY
744 struct AsnDecodeSequenceItem items[] = {
745 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
746 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
747 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
748 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
749 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
750 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
751 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
752 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
753 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
754 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
757 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
758 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
759 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
760 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
761 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
763 __EXCEPT_PAGE_FAULT
765 SetLastError(STATUS_ACCESS_VIOLATION);
766 ret = FALSE;
768 __ENDTRY
770 TRACE("Returning %d (%08x)\n", ret, GetLastError());
771 return ret;
774 /* Internal function */
775 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
776 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
777 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
779 BOOL ret;
780 DWORD dataLen;
782 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
784 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
786 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
787 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
788 pvStructInfo, pcbStructInfo);
790 return ret;
793 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
794 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
795 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
797 BOOL ret;
799 struct AsnDecodeSequenceItem items[] = {
800 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
801 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
802 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
803 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
806 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
807 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
808 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
809 return ret;
812 /* Internal function */
813 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
814 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
815 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
817 BOOL ret;
818 DWORD dataLen;
820 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
822 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
824 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
825 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
826 pDecodePara, pvStructInfo, pcbStructInfo);
828 return ret;
831 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
832 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
833 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
835 BOOL ret = TRUE;
836 struct AsnDecodeSequenceItem items[] = {
837 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
838 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
839 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
840 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
841 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
842 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
843 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
844 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
845 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
846 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
847 Issuer.pbData) },
848 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
849 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
850 FALSE, 0 },
851 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
852 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
853 Subject.pbData) },
854 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
855 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
856 FALSE, TRUE, offsetof(CERT_INFO,
857 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
858 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
859 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
860 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
861 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
862 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
863 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
864 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
865 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
866 offsetof(CERT_INFO, rgExtension), 0 },
869 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
870 pDecodePara, pvStructInfo, *pcbStructInfo);
872 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
873 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
874 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
876 TRACE("Returning %d (%08x)\n", ret, GetLastError());
877 return ret;
880 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
881 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
882 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
884 BOOL ret = TRUE;
886 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
887 pDecodePara, pvStructInfo, *pcbStructInfo);
889 __TRY
891 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
892 DWORD size = 0;
894 /* First try to decode it as a signed cert. */
895 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
896 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
897 (BYTE *)&signedCert, &size);
898 if (ret)
900 size = 0;
901 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
902 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
903 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
904 pcbStructInfo);
905 LocalFree(signedCert);
907 /* Failing that, try it as an unsigned cert */
908 if (!ret)
910 size = 0;
911 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
912 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
913 pDecodePara, pvStructInfo, pcbStructInfo);
916 __EXCEPT_PAGE_FAULT
918 SetLastError(STATUS_ACCESS_VIOLATION);
919 ret = FALSE;
921 __ENDTRY
923 TRACE("Returning %d (%08x)\n", ret, GetLastError());
924 return ret;
927 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
928 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
929 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
931 BOOL ret;
932 struct AsnDecodeSequenceItem items[] = {
933 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
934 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
935 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
936 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
937 sizeof(FILETIME), FALSE, FALSE, 0 },
938 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
939 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
940 offsetof(CRL_ENTRY, rgExtension), 0 },
942 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
944 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
945 *pcbStructInfo);
947 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
948 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
949 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
950 return ret;
953 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
954 * been set prior to calling.
956 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
957 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
958 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
960 BOOL ret;
961 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
962 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
963 offsetof(CRL_ENTRY, SerialNumber.pbData) };
964 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
966 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
967 pDecodePara, pvStructInfo, *pcbStructInfo);
969 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
970 pDecodePara, pvStructInfo, pcbStructInfo,
971 entries ? entries->rgItems : NULL);
972 TRACE("Returning %d (%08x)\n", ret, GetLastError());
973 return ret;
976 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
977 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
978 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
980 struct AsnDecodeSequenceItem items[] = {
981 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
982 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
983 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
984 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
985 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
986 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
987 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
988 Issuer.pbData) },
989 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
990 sizeof(FILETIME), FALSE, FALSE, 0 },
991 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
992 sizeof(FILETIME), TRUE, FALSE, 0 },
993 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
994 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
995 offsetof(CRL_INFO, rgCRLEntry), 0 },
996 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
997 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
998 offsetof(CRL_INFO, rgExtension), 0 },
1000 BOOL ret = TRUE;
1002 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1003 pDecodePara, pvStructInfo, *pcbStructInfo);
1005 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1006 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1007 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1009 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1010 return ret;
1013 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1014 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1015 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1017 BOOL ret = TRUE;
1019 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1020 pDecodePara, pvStructInfo, *pcbStructInfo);
1022 __TRY
1024 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1025 DWORD size = 0;
1027 /* First try to decode it as a signed crl. */
1028 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1029 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1030 (BYTE *)&signedCrl, &size);
1031 if (ret)
1033 size = 0;
1034 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1035 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1036 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1037 pvStructInfo, pcbStructInfo);
1038 LocalFree(signedCrl);
1040 /* Failing that, try it as an unsigned crl */
1041 if (!ret)
1043 size = 0;
1044 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1045 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1046 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1049 __EXCEPT_PAGE_FAULT
1051 SetLastError(STATUS_ACCESS_VIOLATION);
1052 ret = FALSE;
1054 __ENDTRY
1056 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1057 return ret;
1060 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1061 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1062 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1064 BOOL ret = TRUE;
1066 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1067 pDecodePara, pvStructInfo, *pcbStructInfo);
1069 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1071 DWORD dataLen;
1073 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1075 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1076 DWORD bytesNeeded = sizeof(LPSTR);
1078 if (dataLen)
1080 /* The largest possible string for the first two components
1081 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1083 char firstTwo[6];
1084 const BYTE *ptr;
1086 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1087 pbEncoded[1 + lenBytes] / 40,
1088 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1089 * 40);
1090 bytesNeeded += strlen(firstTwo) + 1;
1091 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1092 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1094 /* large enough for ".4000000" */
1095 char str[9];
1096 int val = 0;
1098 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1099 (*ptr & 0x80))
1101 val <<= 7;
1102 val |= *ptr & 0x7f;
1103 ptr++;
1105 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1106 (*ptr & 0x80))
1108 SetLastError(CRYPT_E_ASN1_CORRUPT);
1109 ret = FALSE;
1111 else
1113 val <<= 7;
1114 val |= *ptr++;
1115 snprintf(str, sizeof(str), ".%d", val);
1116 bytesNeeded += strlen(str);
1120 if (!pvStructInfo)
1121 *pcbStructInfo = bytesNeeded;
1122 else if (*pcbStructInfo < bytesNeeded)
1124 *pcbStructInfo = bytesNeeded;
1125 SetLastError(ERROR_MORE_DATA);
1126 ret = FALSE;
1128 else
1130 if (dataLen)
1132 const BYTE *ptr;
1133 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1135 *pszObjId = 0;
1136 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1137 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1138 40) * 40);
1139 pszObjId += strlen(pszObjId);
1140 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1141 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1143 int val = 0;
1145 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1146 (*ptr & 0x80))
1148 val <<= 7;
1149 val |= *ptr & 0x7f;
1150 ptr++;
1152 val <<= 7;
1153 val |= *ptr++;
1154 sprintf(pszObjId, ".%d", val);
1155 pszObjId += strlen(pszObjId);
1158 else
1159 *(LPSTR *)pvStructInfo = NULL;
1160 *pcbStructInfo = bytesNeeded;
1164 return ret;
1167 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1168 * ahead of time!
1170 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1171 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1172 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1174 struct AsnDecodeSequenceItem items[] = {
1175 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1176 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1177 offsetof(CERT_EXTENSION, pszObjId), 0 },
1178 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1179 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1180 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1181 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1182 offsetof(CERT_EXTENSION, Value.pbData) },
1184 BOOL ret = TRUE;
1185 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1187 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1188 *pcbStructInfo);
1190 if (ext)
1191 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1192 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1193 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1194 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1195 if (ext)
1196 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1197 debugstr_a(ext->pszObjId));
1198 TRACE("returning %d (%08x)\n", ret, GetLastError());
1199 return ret;
1202 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1203 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1204 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1206 BOOL ret = TRUE;
1207 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1208 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1209 offsetof(CERT_EXTENSION, pszObjId) };
1210 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1212 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1213 pDecodePara, pvStructInfo, *pcbStructInfo);
1215 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1216 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1217 return ret;
1220 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1221 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1222 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1224 BOOL ret = TRUE;
1226 __TRY
1228 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1229 lpszStructType, pbEncoded, cbEncoded,
1230 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1231 if (ret && pvStructInfo)
1233 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1234 pcbStructInfo, *pcbStructInfo);
1235 if (ret)
1237 CERT_EXTENSIONS *exts;
1239 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1240 pvStructInfo = *(BYTE **)pvStructInfo;
1241 exts = (CERT_EXTENSIONS *)pvStructInfo;
1242 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1243 sizeof(CERT_EXTENSIONS));
1244 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1245 lpszStructType, pbEncoded, cbEncoded,
1246 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1247 pcbStructInfo);
1251 __EXCEPT_PAGE_FAULT
1253 SetLastError(STATUS_ACCESS_VIOLATION);
1254 ret = FALSE;
1256 __ENDTRY
1257 return ret;
1260 /* Warning: this assumes the address of value->Value.pbData is already set, in
1261 * order to avoid overwriting memory. (In some cases, it may change it, if it
1262 * doesn't copy anything to memory.) Be sure to set it correctly!
1264 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1265 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1266 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1268 BOOL ret = TRUE;
1269 DWORD dataLen;
1270 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1272 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1274 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1275 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1277 switch (pbEncoded[0])
1279 case ASN_OCTETSTRING:
1280 valueType = CERT_RDN_OCTET_STRING;
1281 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1282 bytesNeeded += dataLen;
1283 break;
1284 case ASN_NUMERICSTRING:
1285 valueType = CERT_RDN_NUMERIC_STRING;
1286 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1287 bytesNeeded += dataLen;
1288 break;
1289 case ASN_PRINTABLESTRING:
1290 valueType = CERT_RDN_PRINTABLE_STRING;
1291 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1292 bytesNeeded += dataLen;
1293 break;
1294 case ASN_IA5STRING:
1295 valueType = CERT_RDN_IA5_STRING;
1296 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1297 bytesNeeded += dataLen;
1298 break;
1299 case ASN_T61STRING:
1300 valueType = CERT_RDN_T61_STRING;
1301 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1302 bytesNeeded += dataLen;
1303 break;
1304 case ASN_VIDEOTEXSTRING:
1305 valueType = CERT_RDN_VIDEOTEX_STRING;
1306 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1307 bytesNeeded += dataLen;
1308 break;
1309 case ASN_GRAPHICSTRING:
1310 valueType = CERT_RDN_GRAPHIC_STRING;
1311 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1312 bytesNeeded += dataLen;
1313 break;
1314 case ASN_VISIBLESTRING:
1315 valueType = CERT_RDN_VISIBLE_STRING;
1316 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1317 bytesNeeded += dataLen;
1318 break;
1319 case ASN_GENERALSTRING:
1320 valueType = CERT_RDN_GENERAL_STRING;
1321 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1322 bytesNeeded += dataLen;
1323 break;
1324 case ASN_UNIVERSALSTRING:
1325 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1326 SetLastError(CRYPT_E_ASN1_BADTAG);
1327 return FALSE;
1328 case ASN_BMPSTRING:
1329 valueType = CERT_RDN_BMP_STRING;
1330 bytesNeeded += dataLen;
1331 break;
1332 case ASN_UTF8STRING:
1333 valueType = CERT_RDN_UTF8_STRING;
1334 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1335 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1336 break;
1337 default:
1338 SetLastError(CRYPT_E_ASN1_BADTAG);
1339 return FALSE;
1342 if (!value)
1343 *pcbStructInfo = bytesNeeded;
1344 else if (*pcbStructInfo < bytesNeeded)
1346 *pcbStructInfo = bytesNeeded;
1347 SetLastError(ERROR_MORE_DATA);
1348 ret = FALSE;
1350 else
1352 *pcbStructInfo = bytesNeeded;
1353 value->dwValueType = valueType;
1354 if (dataLen)
1356 DWORD i;
1358 assert(value->Value.pbData);
1359 switch (pbEncoded[0])
1361 case ASN_OCTETSTRING:
1362 case ASN_NUMERICSTRING:
1363 case ASN_PRINTABLESTRING:
1364 case ASN_IA5STRING:
1365 case ASN_T61STRING:
1366 case ASN_VIDEOTEXSTRING:
1367 case ASN_GRAPHICSTRING:
1368 case ASN_VISIBLESTRING:
1369 case ASN_GENERALSTRING:
1370 value->Value.cbData = dataLen;
1371 if (dataLen)
1373 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1374 memcpy(value->Value.pbData,
1375 pbEncoded + 1 + lenBytes, dataLen);
1376 else
1377 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1378 lenBytes;
1380 break;
1381 case ASN_BMPSTRING:
1383 LPWSTR str = (LPWSTR)value->Value.pbData;
1385 value->Value.cbData = dataLen;
1386 for (i = 0; i < dataLen / 2; i++)
1387 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1388 pbEncoded[1 + lenBytes + 2 * i + 1];
1389 break;
1391 case ASN_UTF8STRING:
1393 LPWSTR str = (LPWSTR)value->Value.pbData;
1395 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1396 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1397 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1398 break;
1402 else
1404 value->Value.cbData = 0;
1405 value->Value.pbData = NULL;
1409 return ret;
1412 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1413 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1414 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1416 BOOL ret = TRUE;
1418 __TRY
1420 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1421 lpszStructType, pbEncoded, cbEncoded,
1422 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1423 if (ret && pvStructInfo)
1425 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1426 pcbStructInfo, *pcbStructInfo);
1427 if (ret)
1429 CERT_NAME_VALUE *value;
1431 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1432 pvStructInfo = *(BYTE **)pvStructInfo;
1433 value = (CERT_NAME_VALUE *)pvStructInfo;
1434 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1435 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1436 lpszStructType, pbEncoded, cbEncoded,
1437 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1438 pcbStructInfo);
1442 __EXCEPT_PAGE_FAULT
1444 SetLastError(STATUS_ACCESS_VIOLATION);
1445 ret = FALSE;
1447 __ENDTRY
1448 return ret;
1451 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1452 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1453 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1454 void *pvStructInfo, DWORD *pcbStructInfo)
1456 BOOL ret = TRUE;
1457 DWORD dataLen;
1458 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1460 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1462 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1463 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1465 switch (pbEncoded[0])
1467 case ASN_NUMERICSTRING:
1468 valueType = CERT_RDN_NUMERIC_STRING;
1469 bytesNeeded += dataLen * 2;
1470 break;
1471 case ASN_PRINTABLESTRING:
1472 valueType = CERT_RDN_PRINTABLE_STRING;
1473 bytesNeeded += dataLen * 2;
1474 break;
1475 case ASN_IA5STRING:
1476 valueType = CERT_RDN_IA5_STRING;
1477 bytesNeeded += dataLen * 2;
1478 break;
1479 case ASN_T61STRING:
1480 valueType = CERT_RDN_T61_STRING;
1481 bytesNeeded += dataLen * 2;
1482 break;
1483 case ASN_VIDEOTEXSTRING:
1484 valueType = CERT_RDN_VIDEOTEX_STRING;
1485 bytesNeeded += dataLen * 2;
1486 break;
1487 case ASN_GRAPHICSTRING:
1488 valueType = CERT_RDN_GRAPHIC_STRING;
1489 bytesNeeded += dataLen * 2;
1490 break;
1491 case ASN_VISIBLESTRING:
1492 valueType = CERT_RDN_VISIBLE_STRING;
1493 bytesNeeded += dataLen * 2;
1494 break;
1495 case ASN_GENERALSTRING:
1496 valueType = CERT_RDN_GENERAL_STRING;
1497 bytesNeeded += dataLen * 2;
1498 break;
1499 case ASN_UNIVERSALSTRING:
1500 valueType = CERT_RDN_UNIVERSAL_STRING;
1501 bytesNeeded += dataLen / 2;
1502 break;
1503 case ASN_BMPSTRING:
1504 valueType = CERT_RDN_BMP_STRING;
1505 bytesNeeded += dataLen;
1506 break;
1507 case ASN_UTF8STRING:
1508 valueType = CERT_RDN_UTF8_STRING;
1509 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1510 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1511 break;
1512 default:
1513 SetLastError(CRYPT_E_ASN1_BADTAG);
1514 return FALSE;
1517 if (!value)
1518 *pcbStructInfo = bytesNeeded;
1519 else if (*pcbStructInfo < bytesNeeded)
1521 *pcbStructInfo = bytesNeeded;
1522 SetLastError(ERROR_MORE_DATA);
1523 ret = FALSE;
1525 else
1527 *pcbStructInfo = bytesNeeded;
1528 value->dwValueType = valueType;
1529 if (dataLen)
1531 DWORD i;
1532 LPWSTR str = (LPWSTR)value->Value.pbData;
1534 assert(value->Value.pbData);
1535 switch (pbEncoded[0])
1537 case ASN_NUMERICSTRING:
1538 case ASN_PRINTABLESTRING:
1539 case ASN_IA5STRING:
1540 case ASN_T61STRING:
1541 case ASN_VIDEOTEXSTRING:
1542 case ASN_GRAPHICSTRING:
1543 case ASN_VISIBLESTRING:
1544 case ASN_GENERALSTRING:
1545 value->Value.cbData = dataLen * 2;
1546 for (i = 0; i < dataLen; i++)
1547 str[i] = pbEncoded[1 + lenBytes + i];
1548 break;
1549 case ASN_UNIVERSALSTRING:
1550 value->Value.cbData = dataLen / 2;
1551 for (i = 0; i < dataLen / 4; i++)
1552 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1553 | pbEncoded[1 + lenBytes + 2 * i + 3];
1554 break;
1555 case ASN_BMPSTRING:
1556 value->Value.cbData = dataLen;
1557 for (i = 0; i < dataLen / 2; i++)
1558 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1559 pbEncoded[1 + lenBytes + 2 * i + 1];
1560 break;
1561 case ASN_UTF8STRING:
1562 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1563 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1564 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1565 break;
1568 else
1570 value->Value.cbData = 0;
1571 value->Value.pbData = NULL;
1575 return ret;
1578 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1579 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1580 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1582 BOOL ret = TRUE;
1584 __TRY
1586 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1587 lpszStructType, pbEncoded, cbEncoded,
1588 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1589 if (ret && pvStructInfo)
1591 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1592 pcbStructInfo, *pcbStructInfo);
1593 if (ret)
1595 CERT_NAME_VALUE *value;
1597 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1598 pvStructInfo = *(BYTE **)pvStructInfo;
1599 value = (CERT_NAME_VALUE *)pvStructInfo;
1600 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1601 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1602 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1603 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1604 pcbStructInfo);
1608 __EXCEPT_PAGE_FAULT
1610 SetLastError(STATUS_ACCESS_VIOLATION);
1611 ret = FALSE;
1613 __ENDTRY
1614 return ret;
1617 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1618 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1619 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1621 BOOL ret;
1622 struct AsnDecodeSequenceItem items[] = {
1623 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1624 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1625 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1626 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1627 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1628 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1630 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1632 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1633 pvStructInfo, *pcbStructInfo);
1635 if (attr)
1636 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1637 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1638 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1639 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1640 if (attr)
1642 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1643 debugstr_a(attr->pszObjId));
1644 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1646 TRACE("returning %d (%08x)\n", ret, GetLastError());
1647 return ret;
1650 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1651 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1652 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1654 BOOL ret = TRUE;
1655 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1656 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1657 offsetof(CERT_RDN_ATTR, pszObjId) };
1658 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1660 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1661 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1662 return ret;
1665 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1666 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1667 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1669 BOOL ret = TRUE;
1671 __TRY
1673 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1674 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1675 offsetof(CERT_RDN, rgRDNAttr) };
1677 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1678 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1680 __EXCEPT_PAGE_FAULT
1682 SetLastError(STATUS_ACCESS_VIOLATION);
1683 ret = FALSE;
1685 __ENDTRY
1686 return ret;
1689 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
1690 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1691 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1693 BOOL ret;
1694 struct AsnDecodeSequenceItem items[] = {
1695 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1696 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1697 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1698 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1699 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1700 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1702 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1704 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1705 pvStructInfo, *pcbStructInfo);
1707 if (attr)
1708 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1709 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1710 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1711 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1712 if (attr)
1714 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1715 debugstr_a(attr->pszObjId));
1716 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1718 TRACE("returning %d (%08x)\n", ret, GetLastError());
1719 return ret;
1722 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
1723 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1724 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1726 BOOL ret = TRUE;
1727 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1728 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1729 offsetof(CERT_RDN_ATTR, pszObjId) };
1730 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1732 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1733 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1734 return ret;
1737 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1738 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1739 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1741 BOOL ret = TRUE;
1743 __TRY
1745 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1746 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1747 offsetof(CERT_RDN, rgRDNAttr) };
1749 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1750 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1752 __EXCEPT_PAGE_FAULT
1754 SetLastError(STATUS_ACCESS_VIOLATION);
1755 ret = FALSE;
1757 __ENDTRY
1758 return ret;
1761 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1762 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1763 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1765 BOOL ret = TRUE;
1766 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1768 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1769 pDecodePara, pvStructInfo, *pcbStructInfo);
1771 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1772 bytesNeeded += cbEncoded;
1773 if (!pvStructInfo)
1774 *pcbStructInfo = bytesNeeded;
1775 else if (*pcbStructInfo < bytesNeeded)
1777 SetLastError(ERROR_MORE_DATA);
1778 *pcbStructInfo = bytesNeeded;
1779 ret = FALSE;
1781 else
1783 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1785 *pcbStructInfo = bytesNeeded;
1786 blob->cbData = cbEncoded;
1787 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1788 blob->pbData = (LPBYTE)pbEncoded;
1789 else
1791 assert(blob->pbData);
1792 memcpy(blob->pbData, pbEncoded, blob->cbData);
1795 return ret;
1798 static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType,
1799 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1800 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1802 BOOL ret;
1803 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1804 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB), TRUE,
1805 offsetof(CRYPT_DER_BLOB, pbData) };
1806 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1808 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1809 pDecodePara, pvStructInfo, *pcbStructInfo);
1811 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1812 pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
1813 return ret;
1816 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1817 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1818 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1820 BOOL ret = FALSE;
1822 __TRY
1824 struct AsnDecodeSequenceItem items[] = {
1825 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1826 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1827 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1828 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1829 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1830 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1832 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1834 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1835 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1836 pDecodePara, pvStructInfo, pcbStructInfo, attr ? attr->pszObjId :
1837 NULL);
1839 __EXCEPT_PAGE_FAULT
1841 SetLastError(STATUS_ACCESS_VIOLATION);
1843 __ENDTRY
1844 TRACE("returning %d\n", ret);
1845 return ret;
1848 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal(
1849 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1850 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1851 void *pvStructInfo, DWORD *pcbStructInfo)
1853 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1854 CRYPT_AsnDecodePKCSAttribute, sizeof(CRYPT_ATTRIBUTE), TRUE,
1855 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
1856 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1857 BOOL ret;
1859 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1860 pDecodePara, pvStructInfo, pcbStructInfo, attrs ? attrs->rgAttr :
1861 NULL);
1862 return ret;
1865 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
1866 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1867 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1869 BOOL ret = FALSE;
1871 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1872 pDecodePara, pvStructInfo, *pcbStructInfo);
1874 __TRY
1876 DWORD bytesNeeded;
1878 if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1879 lpszStructType, pbEncoded, cbEncoded,
1880 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1882 if (!pvStructInfo)
1883 *pcbStructInfo = bytesNeeded;
1884 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1885 pvStructInfo, pcbStructInfo, bytesNeeded)))
1887 PCRYPT_ATTRIBUTES attrs;
1889 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1890 pvStructInfo = *(BYTE **)pvStructInfo;
1891 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1892 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
1893 sizeof(CRYPT_ATTRIBUTES));
1894 ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1895 lpszStructType, pbEncoded, cbEncoded,
1896 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1897 &bytesNeeded);
1901 __EXCEPT_PAGE_FAULT
1903 SetLastError(STATUS_ACCESS_VIOLATION);
1905 __ENDTRY
1906 TRACE("returning %d\n", ret);
1907 return ret;
1910 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1911 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1912 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1914 CRYPT_ALGORITHM_IDENTIFIER *algo =
1915 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1916 BOOL ret = TRUE;
1917 struct AsnDecodeSequenceItem items[] = {
1918 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1919 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1920 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1921 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1922 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1923 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1926 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1927 pDecodePara, pvStructInfo, *pcbStructInfo);
1929 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1930 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1931 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1932 if (ret && pvStructInfo)
1934 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1935 debugstr_a(algo->pszObjId));
1937 return ret;
1940 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1941 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1942 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1944 BOOL ret = TRUE;
1945 struct AsnDecodeSequenceItem items[] = {
1946 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1947 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1948 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1949 Algorithm.pszObjId) },
1950 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1951 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1952 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1954 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1956 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1957 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1958 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1959 info->Algorithm.Parameters.pbData : NULL);
1960 return ret;
1963 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1964 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1965 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1967 BOOL ret = TRUE;
1969 __TRY
1971 DWORD bytesNeeded;
1973 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1974 lpszStructType, pbEncoded, cbEncoded,
1975 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1977 if (!pvStructInfo)
1978 *pcbStructInfo = bytesNeeded;
1979 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1980 pvStructInfo, pcbStructInfo, bytesNeeded)))
1982 PCERT_PUBLIC_KEY_INFO info;
1984 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1985 pvStructInfo = *(BYTE **)pvStructInfo;
1986 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1987 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
1988 sizeof(CERT_PUBLIC_KEY_INFO);
1989 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1990 lpszStructType, pbEncoded, cbEncoded,
1991 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1992 &bytesNeeded);
1996 __EXCEPT_PAGE_FAULT
1998 SetLastError(STATUS_ACCESS_VIOLATION);
1999 ret = FALSE;
2001 __ENDTRY
2002 return ret;
2005 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2006 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2007 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2009 BOOL ret;
2011 if (cbEncoded < 3)
2013 SetLastError(CRYPT_E_ASN1_CORRUPT);
2014 return FALSE;
2016 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2018 SetLastError(CRYPT_E_ASN1_CORRUPT);
2019 return FALSE;
2021 if (pbEncoded[1] > 1)
2023 SetLastError(CRYPT_E_ASN1_CORRUPT);
2024 return FALSE;
2026 if (!pvStructInfo)
2028 *pcbStructInfo = sizeof(BOOL);
2029 ret = TRUE;
2031 else if (*pcbStructInfo < sizeof(BOOL))
2033 *pcbStructInfo = sizeof(BOOL);
2034 SetLastError(ERROR_MORE_DATA);
2035 ret = FALSE;
2037 else
2039 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2040 ret = TRUE;
2042 TRACE("returning %d (%08x)\n", ret, GetLastError());
2043 return ret;
2046 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
2047 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2048 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2050 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2051 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2052 BOOL ret;
2054 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2055 pDecodePara, pvStructInfo, *pcbStructInfo);
2057 if (cbEncoded < 2)
2059 SetLastError(CRYPT_E_ASN1_CORRUPT);
2060 return FALSE;
2062 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
2064 SetLastError(CRYPT_E_ASN1_BADTAG);
2065 return FALSE;
2067 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2068 if (1 + lenBytes > cbEncoded)
2070 SetLastError(CRYPT_E_ASN1_CORRUPT);
2071 return FALSE;
2073 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2075 switch (pbEncoded[0] & ASN_TYPE_MASK)
2077 case 1: /* rfc822Name */
2078 case 2: /* dNSName */
2079 case 6: /* uniformResourceIdentifier */
2080 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2081 break;
2082 case 7: /* iPAddress */
2083 bytesNeeded += dataLen;
2084 break;
2085 case 8: /* registeredID */
2086 /* FIXME: decode as OID */
2087 case 0: /* otherName */
2088 case 4: /* directoryName */
2089 FIXME("stub\n");
2090 SetLastError(CRYPT_E_ASN1_BADTAG);
2091 ret = FALSE;
2092 break;
2093 case 3: /* x400Address, unimplemented */
2094 case 5: /* ediPartyName, unimplemented */
2095 SetLastError(CRYPT_E_ASN1_BADTAG);
2096 ret = FALSE;
2097 break;
2098 default:
2099 SetLastError(CRYPT_E_ASN1_CORRUPT);
2100 ret = FALSE;
2102 if (ret)
2104 if (!entry)
2105 *pcbStructInfo = bytesNeeded;
2106 else if (*pcbStructInfo < bytesNeeded)
2108 *pcbStructInfo = bytesNeeded;
2109 SetLastError(ERROR_MORE_DATA);
2110 ret = FALSE;
2112 else
2114 *pcbStructInfo = bytesNeeded;
2115 /* MS used values one greater than the asn1 ones.. sigh */
2116 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2117 switch (pbEncoded[0] & ASN_TYPE_MASK)
2119 case 1: /* rfc822Name */
2120 case 2: /* dNSName */
2121 case 6: /* uniformResourceIdentifier */
2123 DWORD i;
2125 for (i = 0; i < dataLen; i++)
2126 entry->u.pwszURL[i] =
2127 (WCHAR)pbEncoded[1 + lenBytes + i];
2128 entry->u.pwszURL[i] = 0;
2129 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2130 debugstr_w(entry->u.pwszURL));
2131 break;
2133 case 7: /* iPAddress */
2134 /* The next data pointer is in the pwszURL spot, that is,
2135 * the first 4 bytes. Need to move it to the next spot.
2137 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2138 entry->u.IPAddress.cbData = dataLen;
2139 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2140 dataLen);
2141 break;
2146 return ret;
2149 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2150 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2151 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2153 BOOL ret = TRUE;
2154 struct AsnArrayDescriptor arrayDesc = { 0,
2155 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2156 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2157 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2159 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2160 pDecodePara, pvStructInfo, *pcbStructInfo);
2162 if (info)
2163 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2164 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2165 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2166 return ret;
2169 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2170 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2171 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2173 BOOL ret;
2175 __TRY
2177 struct AsnDecodeSequenceItem items[] = {
2178 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2179 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2180 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2181 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2182 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2183 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2184 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2185 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2186 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2187 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2188 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2191 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2192 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2193 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2195 __EXCEPT_PAGE_FAULT
2197 SetLastError(STATUS_ACCESS_VIOLATION);
2198 ret = FALSE;
2200 __ENDTRY
2201 return ret;
2204 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2205 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2206 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2208 BOOL ret;
2210 __TRY
2212 struct AsnDecodeSequenceItem items[] = {
2213 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2214 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2215 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2216 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2217 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2218 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2219 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2220 AuthorityCertIssuer.rgAltEntry), 0 },
2221 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2222 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2223 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2224 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2225 AuthorityCertSerialNumber.pbData), 0 },
2228 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2229 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2230 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2232 __EXCEPT_PAGE_FAULT
2234 SetLastError(STATUS_ACCESS_VIOLATION);
2235 ret = FALSE;
2237 __ENDTRY
2238 return ret;
2241 static BOOL WINAPI CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType,
2242 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2243 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2245 BOOL ret;
2246 DWORD dataLen;
2248 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2249 pDecodePara, pvStructInfo, *pcbStructInfo);
2251 /* The caller has already checked the tag, no need to check it again.
2252 * Check the outer length is valid by calling CRYPT_GetLen:
2254 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2256 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2257 DWORD innerLen;
2259 pbEncoded += 1 + lenBytes;
2260 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2261 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2263 ret = CRYPT_AsnDecodeCopyBytes(dwCertEncodingType, NULL,
2264 pbEncoded, dataLen, dwFlags, pDecodePara, pvStructInfo,
2265 pcbStructInfo);
2268 return ret;
2271 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2272 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2273 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2275 BOOL ret = FALSE;
2277 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2278 pDecodePara, pvStructInfo, *pcbStructInfo);
2280 __TRY
2282 struct AsnDecodeSequenceItem items[] = {
2283 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2284 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
2285 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2286 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2287 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2288 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2289 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2292 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2293 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2294 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2296 __EXCEPT_PAGE_FAULT
2298 SetLastError(STATUS_ACCESS_VIOLATION);
2300 __ENDTRY
2301 return ret;
2302 return ret;
2305 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2306 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2307 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2309 BOOL ret = TRUE;
2311 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2312 pDecodePara, pvStructInfo, *pcbStructInfo);
2314 __TRY
2316 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2317 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2318 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2320 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2321 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2323 __EXCEPT_PAGE_FAULT
2325 SetLastError(STATUS_ACCESS_VIOLATION);
2326 ret = FALSE;
2328 __ENDTRY
2329 return ret;
2332 struct PATH_LEN_CONSTRAINT
2334 BOOL fPathLenConstraint;
2335 DWORD dwPathLenConstraint;
2338 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2339 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2340 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2342 BOOL ret = TRUE;
2344 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2345 pvStructInfo, *pcbStructInfo);
2347 if (cbEncoded)
2349 if (pbEncoded[0] == ASN_INTEGER)
2351 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2353 if (!pvStructInfo)
2354 *pcbStructInfo = bytesNeeded;
2355 else if (*pcbStructInfo < bytesNeeded)
2357 SetLastError(ERROR_MORE_DATA);
2358 *pcbStructInfo = bytesNeeded;
2359 ret = FALSE;
2361 else
2363 struct PATH_LEN_CONSTRAINT *constraint =
2364 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2365 DWORD size = sizeof(constraint->dwPathLenConstraint);
2367 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2368 pbEncoded, cbEncoded, 0, NULL,
2369 &constraint->dwPathLenConstraint, &size);
2370 if (ret)
2371 constraint->fPathLenConstraint = TRUE;
2372 TRACE("got an int, dwPathLenConstraint is %d\n",
2373 constraint->dwPathLenConstraint);
2376 else
2378 SetLastError(CRYPT_E_ASN1_CORRUPT);
2379 ret = FALSE;
2382 TRACE("returning %d (%08x)\n", ret, GetLastError());
2383 return ret;
2386 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2387 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2388 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2390 BOOL ret;
2391 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2392 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2393 offsetof(CERT_NAME_BLOB, pbData) };
2394 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2396 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2397 pDecodePara, pvStructInfo, *pcbStructInfo);
2399 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2400 pDecodePara, pvStructInfo, pcbStructInfo,
2401 entries ? entries->rgItems : NULL);
2402 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2403 return ret;
2406 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2407 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2408 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2410 BOOL ret;
2412 __TRY
2414 struct AsnDecodeSequenceItem items[] = {
2415 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2416 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2417 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2418 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2419 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2420 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2421 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2422 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2423 sizeof(struct GenericArray), TRUE, TRUE,
2424 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2427 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2428 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2429 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2431 __EXCEPT_PAGE_FAULT
2433 SetLastError(STATUS_ACCESS_VIOLATION);
2434 ret = FALSE;
2436 __ENDTRY
2437 return ret;
2440 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2441 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2442 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2444 BOOL ret;
2446 __TRY
2448 struct AsnDecodeSequenceItem items[] = {
2449 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2450 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2451 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2452 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2453 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2456 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2457 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2458 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2460 __EXCEPT_PAGE_FAULT
2462 SetLastError(STATUS_ACCESS_VIOLATION);
2463 ret = FALSE;
2465 __ENDTRY
2466 return ret;
2469 #define RSA1_MAGIC 0x31415352
2471 struct DECODED_RSA_PUB_KEY
2473 DWORD pubexp;
2474 CRYPT_INTEGER_BLOB modulus;
2477 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2478 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2479 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2481 BOOL ret;
2483 __TRY
2485 struct AsnDecodeSequenceItem items[] = {
2486 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2487 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2488 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2489 0 },
2490 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2491 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2493 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2494 DWORD size = 0;
2496 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2497 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2498 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2499 if (ret)
2501 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2502 decodedKey->modulus.cbData;
2504 if (!pvStructInfo)
2506 *pcbStructInfo = bytesNeeded;
2507 ret = TRUE;
2509 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2510 pvStructInfo, pcbStructInfo, bytesNeeded)))
2512 BLOBHEADER *hdr;
2513 RSAPUBKEY *rsaPubKey;
2515 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2516 pvStructInfo = *(BYTE **)pvStructInfo;
2517 hdr = (BLOBHEADER *)pvStructInfo;
2518 hdr->bType = PUBLICKEYBLOB;
2519 hdr->bVersion = CUR_BLOB_VERSION;
2520 hdr->reserved = 0;
2521 hdr->aiKeyAlg = CALG_RSA_KEYX;
2522 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2523 sizeof(BLOBHEADER));
2524 rsaPubKey->magic = RSA1_MAGIC;
2525 rsaPubKey->pubexp = decodedKey->pubexp;
2526 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2527 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2528 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2529 decodedKey->modulus.cbData);
2531 LocalFree(decodedKey);
2534 __EXCEPT_PAGE_FAULT
2536 SetLastError(STATUS_ACCESS_VIOLATION);
2537 ret = FALSE;
2539 __ENDTRY
2540 return ret;
2543 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2544 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2545 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2547 BOOL ret;
2548 DWORD bytesNeeded, dataLen;
2550 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2551 pDecodePara, pvStructInfo, *pcbStructInfo);
2553 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2555 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2556 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2557 else
2558 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2559 if (!pvStructInfo)
2560 *pcbStructInfo = bytesNeeded;
2561 else if (*pcbStructInfo < bytesNeeded)
2563 SetLastError(ERROR_MORE_DATA);
2564 *pcbStructInfo = bytesNeeded;
2565 ret = FALSE;
2567 else
2569 CRYPT_DATA_BLOB *blob;
2570 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2572 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2573 blob->cbData = dataLen;
2574 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2575 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2576 else
2578 assert(blob->pbData);
2579 if (blob->cbData)
2580 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2581 blob->cbData);
2585 return ret;
2588 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2589 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2590 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2592 BOOL ret;
2594 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2595 pDecodePara, pvStructInfo, *pcbStructInfo);
2597 __TRY
2599 DWORD bytesNeeded;
2601 if (!cbEncoded)
2603 SetLastError(CRYPT_E_ASN1_CORRUPT);
2604 ret = FALSE;
2606 else if (pbEncoded[0] != ASN_OCTETSTRING)
2608 SetLastError(CRYPT_E_ASN1_BADTAG);
2609 ret = FALSE;
2611 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2612 lpszStructType, pbEncoded, cbEncoded,
2613 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2615 if (!pvStructInfo)
2616 *pcbStructInfo = bytesNeeded;
2617 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2618 pvStructInfo, pcbStructInfo, bytesNeeded)))
2620 CRYPT_DATA_BLOB *blob;
2622 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2623 pvStructInfo = *(BYTE **)pvStructInfo;
2624 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2625 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2626 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2627 lpszStructType, pbEncoded, cbEncoded,
2628 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2629 &bytesNeeded);
2633 __EXCEPT_PAGE_FAULT
2635 SetLastError(STATUS_ACCESS_VIOLATION);
2636 ret = FALSE;
2638 __ENDTRY
2639 return ret;
2642 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2643 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2644 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2646 BOOL ret;
2648 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2649 pDecodePara, pvStructInfo, *pcbStructInfo);
2651 if (pbEncoded[0] == ASN_BITSTRING)
2653 DWORD bytesNeeded, dataLen;
2655 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2657 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2658 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2659 else
2660 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2661 if (!pvStructInfo)
2662 *pcbStructInfo = bytesNeeded;
2663 else if (*pcbStructInfo < bytesNeeded)
2665 *pcbStructInfo = bytesNeeded;
2666 SetLastError(ERROR_MORE_DATA);
2667 ret = FALSE;
2669 else
2671 CRYPT_BIT_BLOB *blob;
2673 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2674 blob->cbData = dataLen - 1;
2675 blob->cUnusedBits = *(pbEncoded + 1 +
2676 GET_LEN_BYTES(pbEncoded[1]));
2677 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2679 blob->pbData = (BYTE *)pbEncoded + 2 +
2680 GET_LEN_BYTES(pbEncoded[1]);
2682 else
2684 assert(blob->pbData);
2685 if (blob->cbData)
2687 BYTE mask = 0xff << blob->cUnusedBits;
2689 memcpy(blob->pbData, pbEncoded + 2 +
2690 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2691 blob->pbData[blob->cbData - 1] &= mask;
2697 else
2699 SetLastError(CRYPT_E_ASN1_BADTAG);
2700 ret = FALSE;
2702 TRACE("returning %d (%08x)\n", ret, GetLastError());
2703 return ret;
2706 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2707 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2708 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2710 BOOL ret;
2712 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2713 pDecodePara, pvStructInfo, pcbStructInfo);
2715 __TRY
2717 DWORD bytesNeeded;
2719 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2720 lpszStructType, pbEncoded, cbEncoded,
2721 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2723 if (!pvStructInfo)
2724 *pcbStructInfo = bytesNeeded;
2725 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2726 pvStructInfo, pcbStructInfo, bytesNeeded)))
2728 CRYPT_BIT_BLOB *blob;
2730 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2731 pvStructInfo = *(BYTE **)pvStructInfo;
2732 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2733 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2734 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2735 lpszStructType, pbEncoded, cbEncoded,
2736 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2737 &bytesNeeded);
2741 __EXCEPT_PAGE_FAULT
2743 SetLastError(STATUS_ACCESS_VIOLATION);
2744 ret = FALSE;
2746 __ENDTRY
2747 TRACE("returning %d (%08x)\n", ret, GetLastError());
2748 return ret;
2751 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2752 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2753 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2755 BOOL ret;
2757 if (!pvStructInfo)
2759 *pcbStructInfo = sizeof(int);
2760 return TRUE;
2762 __TRY
2764 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2765 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2766 DWORD size = sizeof(buf);
2768 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2769 if (pbEncoded[0] != ASN_INTEGER)
2771 SetLastError(CRYPT_E_ASN1_BADTAG);
2772 ret = FALSE;
2774 else
2775 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2776 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
2777 &size);
2778 if (ret)
2780 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2781 pvStructInfo, pcbStructInfo, sizeof(int))))
2783 int val, i;
2785 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2786 pvStructInfo = *(BYTE **)pvStructInfo;
2787 if (blob->pbData[blob->cbData - 1] & 0x80)
2789 /* initialize to a negative value to sign-extend */
2790 val = -1;
2792 else
2793 val = 0;
2794 for (i = 0; i < blob->cbData; i++)
2796 val <<= 8;
2797 val |= blob->pbData[blob->cbData - i - 1];
2799 memcpy(pvStructInfo, &val, sizeof(int));
2802 else if (GetLastError() == ERROR_MORE_DATA)
2803 SetLastError(CRYPT_E_ASN1_LARGE);
2805 __EXCEPT_PAGE_FAULT
2807 SetLastError(STATUS_ACCESS_VIOLATION);
2808 ret = FALSE;
2810 __ENDTRY
2811 return ret;
2814 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2815 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2816 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2818 BOOL ret;
2819 DWORD bytesNeeded, dataLen;
2821 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2823 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2825 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2826 if (!pvStructInfo)
2827 *pcbStructInfo = bytesNeeded;
2828 else if (*pcbStructInfo < bytesNeeded)
2830 *pcbStructInfo = bytesNeeded;
2831 SetLastError(ERROR_MORE_DATA);
2832 ret = FALSE;
2834 else
2836 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2838 blob->cbData = dataLen;
2839 assert(blob->pbData);
2840 if (blob->cbData)
2842 DWORD i;
2844 for (i = 0; i < blob->cbData; i++)
2846 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2847 dataLen - i - 1);
2852 return ret;
2855 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2856 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2857 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2859 BOOL ret;
2861 __TRY
2863 DWORD bytesNeeded;
2865 if (pbEncoded[0] != ASN_INTEGER)
2867 SetLastError(CRYPT_E_ASN1_BADTAG);
2868 ret = FALSE;
2870 else
2871 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2872 lpszStructType, pbEncoded, cbEncoded,
2873 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
2874 if (ret)
2876 if (!pvStructInfo)
2877 *pcbStructInfo = bytesNeeded;
2878 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2879 pvStructInfo, pcbStructInfo, bytesNeeded)))
2881 CRYPT_INTEGER_BLOB *blob;
2883 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2884 pvStructInfo = *(BYTE **)pvStructInfo;
2885 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2886 blob->pbData = (BYTE *)pvStructInfo +
2887 sizeof(CRYPT_INTEGER_BLOB);
2888 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2889 lpszStructType, pbEncoded, cbEncoded,
2890 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2891 &bytesNeeded);
2895 __EXCEPT_PAGE_FAULT
2897 SetLastError(STATUS_ACCESS_VIOLATION);
2898 ret = FALSE;
2900 __ENDTRY
2901 return ret;
2904 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
2905 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2906 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2907 void *pvStructInfo, DWORD *pcbStructInfo)
2909 BOOL ret;
2911 if (pbEncoded[0] == ASN_INTEGER)
2913 DWORD bytesNeeded, dataLen;
2915 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2917 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2919 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2920 if (!pvStructInfo)
2921 *pcbStructInfo = bytesNeeded;
2922 else if (*pcbStructInfo < bytesNeeded)
2924 *pcbStructInfo = bytesNeeded;
2925 SetLastError(ERROR_MORE_DATA);
2926 ret = FALSE;
2928 else
2930 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2932 blob->cbData = dataLen;
2933 assert(blob->pbData);
2934 /* remove leading zero byte if it exists */
2935 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2937 blob->cbData--;
2938 blob->pbData++;
2940 if (blob->cbData)
2942 DWORD i;
2944 for (i = 0; i < blob->cbData; i++)
2946 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2947 dataLen - i - 1);
2953 else
2955 SetLastError(CRYPT_E_ASN1_BADTAG);
2956 ret = FALSE;
2958 return ret;
2961 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2962 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2963 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2965 BOOL ret;
2967 __TRY
2969 DWORD bytesNeeded;
2971 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2972 lpszStructType, pbEncoded, cbEncoded,
2973 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2975 if (!pvStructInfo)
2976 *pcbStructInfo = bytesNeeded;
2977 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2978 pvStructInfo, pcbStructInfo, bytesNeeded)))
2980 CRYPT_INTEGER_BLOB *blob;
2982 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2983 pvStructInfo = *(BYTE **)pvStructInfo;
2984 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2985 blob->pbData = (BYTE *)pvStructInfo +
2986 sizeof(CRYPT_INTEGER_BLOB);
2987 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2988 lpszStructType, pbEncoded, cbEncoded,
2989 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2990 &bytesNeeded);
2994 __EXCEPT_PAGE_FAULT
2996 SetLastError(STATUS_ACCESS_VIOLATION);
2997 ret = FALSE;
2999 __ENDTRY
3000 return ret;
3003 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3004 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3005 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3007 BOOL ret;
3009 if (!pvStructInfo)
3011 *pcbStructInfo = sizeof(int);
3012 return TRUE;
3014 __TRY
3016 if (pbEncoded[0] == ASN_ENUMERATED)
3018 unsigned int val = 0, i;
3020 if (cbEncoded <= 1)
3022 SetLastError(CRYPT_E_ASN1_EOD);
3023 ret = FALSE;
3025 else if (pbEncoded[1] == 0)
3027 SetLastError(CRYPT_E_ASN1_CORRUPT);
3028 ret = FALSE;
3030 else
3032 /* A little strange looking, but we have to accept a sign byte:
3033 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3034 * assuming a small length is okay here, it has to be in short
3035 * form.
3037 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3039 SetLastError(CRYPT_E_ASN1_LARGE);
3040 return FALSE;
3042 for (i = 0; i < pbEncoded[1]; i++)
3044 val <<= 8;
3045 val |= pbEncoded[2 + i];
3047 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3048 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3050 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3051 pvStructInfo = *(BYTE **)pvStructInfo;
3052 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3056 else
3058 SetLastError(CRYPT_E_ASN1_BADTAG);
3059 ret = FALSE;
3062 __EXCEPT_PAGE_FAULT
3064 SetLastError(STATUS_ACCESS_VIOLATION);
3065 ret = FALSE;
3067 __ENDTRY
3068 return ret;
3071 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3072 * if it fails.
3074 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3075 do { \
3076 BYTE i; \
3078 (word) = 0; \
3079 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3081 if (!isdigit(*(pbEncoded))) \
3083 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3084 ret = FALSE; \
3086 else \
3088 (word) *= 10; \
3089 (word) += *(pbEncoded)++ - '0'; \
3092 } while (0)
3094 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3095 SYSTEMTIME *sysTime)
3097 BOOL ret;
3099 __TRY
3101 ret = TRUE;
3102 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3104 WORD hours, minutes = 0;
3105 BYTE sign = *pbEncoded++;
3107 len--;
3108 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3109 if (ret && hours >= 24)
3111 SetLastError(CRYPT_E_ASN1_CORRUPT);
3112 ret = FALSE;
3114 else if (len >= 2)
3116 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3117 if (ret && minutes >= 60)
3119 SetLastError(CRYPT_E_ASN1_CORRUPT);
3120 ret = FALSE;
3123 if (ret)
3125 if (sign == '+')
3127 sysTime->wHour += hours;
3128 sysTime->wMinute += minutes;
3130 else
3132 if (hours > sysTime->wHour)
3134 sysTime->wDay--;
3135 sysTime->wHour = 24 - (hours - sysTime->wHour);
3137 else
3138 sysTime->wHour -= hours;
3139 if (minutes > sysTime->wMinute)
3141 sysTime->wHour--;
3142 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3144 else
3145 sysTime->wMinute -= minutes;
3150 __EXCEPT_PAGE_FAULT
3152 SetLastError(STATUS_ACCESS_VIOLATION);
3153 ret = FALSE;
3155 __ENDTRY
3156 return ret;
3159 #define MIN_ENCODED_TIME_LENGTH 10
3161 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3162 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3163 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3165 BOOL ret;
3167 if (!pvStructInfo)
3169 *pcbStructInfo = sizeof(FILETIME);
3170 return TRUE;
3172 __TRY
3174 ret = TRUE;
3175 if (pbEncoded[0] == ASN_UTCTIME)
3177 if (cbEncoded <= 1)
3179 SetLastError(CRYPT_E_ASN1_EOD);
3180 ret = FALSE;
3182 else if (pbEncoded[1] > 0x7f)
3184 /* long-form date strings really can't be valid */
3185 SetLastError(CRYPT_E_ASN1_CORRUPT);
3186 ret = FALSE;
3188 else
3190 SYSTEMTIME sysTime = { 0 };
3191 BYTE len = pbEncoded[1];
3193 if (len < MIN_ENCODED_TIME_LENGTH)
3195 SetLastError(CRYPT_E_ASN1_CORRUPT);
3196 ret = FALSE;
3198 else
3200 pbEncoded += 2;
3201 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3202 if (sysTime.wYear >= 50)
3203 sysTime.wYear += 1900;
3204 else
3205 sysTime.wYear += 2000;
3206 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3207 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3208 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3209 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3210 if (ret && len > 0)
3212 if (len >= 2 && isdigit(*pbEncoded) &&
3213 isdigit(*(pbEncoded + 1)))
3214 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3215 sysTime.wSecond);
3216 else if (isdigit(*pbEncoded))
3217 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3218 sysTime.wSecond);
3219 if (ret)
3220 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3221 &sysTime);
3223 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3224 pDecodePara, pvStructInfo, pcbStructInfo,
3225 sizeof(FILETIME))))
3227 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3228 pvStructInfo = *(BYTE **)pvStructInfo;
3229 ret = SystemTimeToFileTime(&sysTime,
3230 (FILETIME *)pvStructInfo);
3235 else
3237 SetLastError(CRYPT_E_ASN1_BADTAG);
3238 ret = FALSE;
3241 __EXCEPT_PAGE_FAULT
3243 SetLastError(STATUS_ACCESS_VIOLATION);
3244 ret = FALSE;
3246 __ENDTRY
3247 return ret;
3250 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3251 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3252 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3254 BOOL ret;
3256 if (!pvStructInfo)
3258 *pcbStructInfo = sizeof(FILETIME);
3259 return TRUE;
3261 __TRY
3263 ret = TRUE;
3264 if (pbEncoded[0] == ASN_GENERALTIME)
3266 if (cbEncoded <= 1)
3268 SetLastError(CRYPT_E_ASN1_EOD);
3269 ret = FALSE;
3271 else if (pbEncoded[1] > 0x7f)
3273 /* long-form date strings really can't be valid */
3274 SetLastError(CRYPT_E_ASN1_CORRUPT);
3275 ret = FALSE;
3277 else
3279 BYTE len = pbEncoded[1];
3281 if (len < MIN_ENCODED_TIME_LENGTH)
3283 SetLastError(CRYPT_E_ASN1_CORRUPT);
3284 ret = FALSE;
3286 else
3288 SYSTEMTIME sysTime = { 0 };
3290 pbEncoded += 2;
3291 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3292 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3293 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3294 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3295 if (ret && len > 0)
3297 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3298 sysTime.wMinute);
3299 if (ret && len > 0)
3300 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3301 sysTime.wSecond);
3302 if (ret && len > 0 && (*pbEncoded == '.' ||
3303 *pbEncoded == ','))
3305 BYTE digits;
3307 pbEncoded++;
3308 len--;
3309 /* workaround macro weirdness */
3310 digits = min(len, 3);
3311 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3312 sysTime.wMilliseconds);
3314 if (ret)
3315 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3316 &sysTime);
3318 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3319 pDecodePara, pvStructInfo, pcbStructInfo,
3320 sizeof(FILETIME))))
3322 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3323 pvStructInfo = *(BYTE **)pvStructInfo;
3324 ret = SystemTimeToFileTime(&sysTime,
3325 (FILETIME *)pvStructInfo);
3330 else
3332 SetLastError(CRYPT_E_ASN1_BADTAG);
3333 ret = FALSE;
3336 __EXCEPT_PAGE_FAULT
3338 SetLastError(STATUS_ACCESS_VIOLATION);
3339 ret = FALSE;
3341 __ENDTRY
3342 return ret;
3345 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3346 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3347 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3349 BOOL ret;
3351 __TRY
3353 if (pbEncoded[0] == ASN_UTCTIME)
3354 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3355 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3356 pcbStructInfo);
3357 else if (pbEncoded[0] == ASN_GENERALTIME)
3358 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3359 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3360 pvStructInfo, pcbStructInfo);
3361 else
3363 SetLastError(CRYPT_E_ASN1_BADTAG);
3364 ret = FALSE;
3367 __EXCEPT_PAGE_FAULT
3369 SetLastError(STATUS_ACCESS_VIOLATION);
3370 ret = FALSE;
3372 __ENDTRY
3373 return ret;
3376 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3377 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3378 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3380 BOOL ret = TRUE;
3382 __TRY
3384 if (pbEncoded[0] == ASN_SEQUENCEOF)
3386 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3388 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3390 BYTE lenBytes;
3391 const BYTE *ptr;
3393 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3394 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3395 cValue = 0;
3396 ptr = pbEncoded + 1 + lenBytes;
3397 remainingLen = dataLen;
3398 while (ret && remainingLen)
3400 DWORD nextLen;
3402 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3403 if (ret)
3405 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3407 remainingLen -= 1 + nextLenBytes + nextLen;
3408 ptr += 1 + nextLenBytes + nextLen;
3409 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3410 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3411 bytesNeeded += 1 + nextLenBytes + nextLen;
3412 cValue++;
3415 if (ret)
3417 CRYPT_SEQUENCE_OF_ANY *seq;
3418 BYTE *nextPtr;
3419 DWORD i;
3421 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3422 pvStructInfo, pcbStructInfo, bytesNeeded)))
3424 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3425 pvStructInfo = *(BYTE **)pvStructInfo;
3426 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3427 seq->cValue = cValue;
3428 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3429 sizeof(*seq));
3430 nextPtr = (BYTE *)seq->rgValue +
3431 cValue * sizeof(CRYPT_DER_BLOB);
3432 ptr = pbEncoded + 1 + lenBytes;
3433 remainingLen = dataLen;
3434 i = 0;
3435 while (ret && remainingLen)
3437 DWORD nextLen;
3439 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3440 if (ret)
3442 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3444 seq->rgValue[i].cbData = 1 + nextLenBytes +
3445 nextLen;
3446 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3447 seq->rgValue[i].pbData = (BYTE *)ptr;
3448 else
3450 seq->rgValue[i].pbData = nextPtr;
3451 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3452 nextLen);
3453 nextPtr += 1 + nextLenBytes + nextLen;
3455 remainingLen -= 1 + nextLenBytes + nextLen;
3456 ptr += 1 + nextLenBytes + nextLen;
3457 i++;
3464 else
3466 SetLastError(CRYPT_E_ASN1_BADTAG);
3467 ret = FALSE;
3470 __EXCEPT_PAGE_FAULT
3472 SetLastError(STATUS_ACCESS_VIOLATION);
3473 ret = FALSE;
3475 __ENDTRY
3476 return ret;
3479 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3480 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3481 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3483 BOOL ret;
3485 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3487 DWORD bytesNeeded, dataLen;
3489 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3491 struct AsnArrayDescriptor arrayDesc = {
3492 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3493 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3494 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3495 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3497 if (dataLen)
3499 DWORD nameLen;
3501 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3502 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3503 0, NULL, NULL, &nameLen, NULL);
3504 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3506 else
3507 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3508 if (!pvStructInfo)
3509 *pcbStructInfo = bytesNeeded;
3510 else if (*pcbStructInfo < bytesNeeded)
3512 *pcbStructInfo = bytesNeeded;
3513 SetLastError(ERROR_MORE_DATA);
3514 ret = FALSE;
3516 else
3518 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3520 if (dataLen)
3522 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3523 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3524 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3525 0, NULL, &name->u.FullName, pcbStructInfo,
3526 name->u.FullName.rgAltEntry);
3528 else
3529 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3533 else
3535 SetLastError(CRYPT_E_ASN1_BADTAG);
3536 ret = FALSE;
3538 return ret;
3541 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3542 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3543 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3545 struct AsnDecodeSequenceItem items[] = {
3546 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3547 DistPointName), CRYPT_AsnDecodeDistPointName,
3548 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3549 DistPointName.u.FullName.rgAltEntry), 0 },
3550 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3551 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3552 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3553 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3554 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3555 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3557 BOOL ret;
3559 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3560 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3561 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3562 return ret;
3565 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3566 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3567 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3569 BOOL ret;
3571 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3572 pDecodePara, pvStructInfo, *pcbStructInfo);
3574 __TRY
3576 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3577 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3578 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3580 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3581 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3583 __EXCEPT_PAGE_FAULT
3585 SetLastError(STATUS_ACCESS_VIOLATION);
3586 ret = FALSE;
3588 __ENDTRY
3589 return ret;
3592 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3593 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3594 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3596 BOOL ret;
3598 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3599 pDecodePara, pvStructInfo, *pcbStructInfo);
3601 __TRY
3603 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3604 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3606 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3607 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3609 __EXCEPT_PAGE_FAULT
3611 SetLastError(STATUS_ACCESS_VIOLATION);
3612 ret = FALSE;
3614 __ENDTRY
3615 return ret;
3618 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3619 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3620 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3622 BOOL ret;
3624 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3625 pDecodePara, pvStructInfo, *pcbStructInfo);
3627 __TRY
3629 struct AsnDecodeSequenceItem items[] = {
3630 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3631 DistPointName), CRYPT_AsnDecodeDistPointName,
3632 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3633 offsetof(CRL_ISSUING_DIST_POINT,
3634 DistPointName.u.FullName.rgAltEntry), 0 },
3635 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3636 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3637 FALSE, 0 },
3638 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3639 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3640 FALSE, 0 },
3641 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3642 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3643 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3644 OnlySomeReasonFlags.pbData), 0 },
3645 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3646 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3649 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3650 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3651 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3653 __EXCEPT_PAGE_FAULT
3655 SetLastError(STATUS_ACCESS_VIOLATION);
3656 ret = FALSE;
3658 __ENDTRY
3659 return ret;
3662 static BOOL WINAPI CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType,
3663 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3664 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3666 BOOL ret;
3667 struct AsnDecodeSequenceItem items[] = {
3668 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
3669 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
3670 Issuer.pbData) },
3671 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
3672 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
3673 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
3675 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3676 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3678 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3679 pDecodePara, pvStructInfo, *pcbStructInfo);
3681 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3682 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3683 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
3684 issuerSerial ? issuerSerial->Issuer.pbData : NULL);
3685 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
3687 SetLastError(CRYPT_E_ASN1_CORRUPT);
3688 ret = FALSE;
3690 TRACE("returning %d\n", ret);
3691 return ret;
3694 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
3695 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3696 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3698 BOOL ret = FALSE;
3700 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3701 pDecodePara, pvStructInfo, *pcbStructInfo);
3703 __TRY
3705 struct AsnDecodeSequenceItem items[] = {
3706 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
3707 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3708 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
3709 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
3710 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
3711 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
3712 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3713 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
3714 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
3715 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3716 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
3717 HashEncryptionAlgorithm.pszObjId), 0 },
3718 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CMSG_SIGNER_INFO, AuthAttrs),
3719 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3720 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
3721 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
3722 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3723 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
3724 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
3725 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
3726 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
3729 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3730 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3731 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3733 __EXCEPT_PAGE_FAULT
3735 SetLastError(STATUS_ACCESS_VIOLATION);
3737 __ENDTRY
3738 TRACE("returning %d\n", ret);
3739 return ret;
3742 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3743 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3744 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3746 static HCRYPTOIDFUNCSET set = NULL;
3747 BOOL ret = FALSE;
3748 CryptDecodeObjectExFunc decodeFunc = NULL;
3749 HCRYPTOIDFUNCADDR hFunc = NULL;
3751 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
3752 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
3753 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3755 if (!pvStructInfo && !pcbStructInfo)
3757 SetLastError(ERROR_INVALID_PARAMETER);
3758 return FALSE;
3760 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3761 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3763 SetLastError(ERROR_FILE_NOT_FOUND);
3764 return FALSE;
3766 if (!cbEncoded)
3768 SetLastError(CRYPT_E_ASN1_EOD);
3769 return FALSE;
3771 if (cbEncoded > MAX_ENCODED_LEN)
3773 SetLastError(CRYPT_E_ASN1_LARGE);
3774 return FALSE;
3777 SetLastError(NOERROR);
3778 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3779 *(BYTE **)pvStructInfo = NULL;
3780 if (!HIWORD(lpszStructType))
3782 switch (LOWORD(lpszStructType))
3784 case (WORD)X509_CERT:
3785 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3786 break;
3787 case (WORD)X509_CERT_TO_BE_SIGNED:
3788 decodeFunc = CRYPT_AsnDecodeCert;
3789 break;
3790 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3791 decodeFunc = CRYPT_AsnDecodeCRL;
3792 break;
3793 case (WORD)X509_EXTENSIONS:
3794 decodeFunc = CRYPT_AsnDecodeExtensions;
3795 break;
3796 case (WORD)X509_NAME_VALUE:
3797 decodeFunc = CRYPT_AsnDecodeNameValue;
3798 break;
3799 case (WORD)X509_NAME:
3800 decodeFunc = CRYPT_AsnDecodeName;
3801 break;
3802 case (WORD)X509_PUBLIC_KEY_INFO:
3803 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
3804 break;
3805 case (WORD)X509_AUTHORITY_KEY_ID:
3806 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3807 break;
3808 case (WORD)X509_ALTERNATE_NAME:
3809 decodeFunc = CRYPT_AsnDecodeAltName;
3810 break;
3811 case (WORD)X509_BASIC_CONSTRAINTS:
3812 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3813 break;
3814 case (WORD)X509_BASIC_CONSTRAINTS2:
3815 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3816 break;
3817 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3818 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3819 break;
3820 case (WORD)X509_UNICODE_NAME:
3821 decodeFunc = CRYPT_AsnDecodeUnicodeName;
3822 break;
3823 case (WORD)PKCS_ATTRIBUTE:
3824 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
3825 break;
3826 case (WORD)X509_UNICODE_NAME_VALUE:
3827 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
3828 break;
3829 case (WORD)X509_OCTET_STRING:
3830 decodeFunc = CRYPT_AsnDecodeOctets;
3831 break;
3832 case (WORD)X509_BITS:
3833 case (WORD)X509_KEY_USAGE:
3834 decodeFunc = CRYPT_AsnDecodeBits;
3835 break;
3836 case (WORD)X509_INTEGER:
3837 decodeFunc = CRYPT_AsnDecodeInt;
3838 break;
3839 case (WORD)X509_MULTI_BYTE_INTEGER:
3840 decodeFunc = CRYPT_AsnDecodeInteger;
3841 break;
3842 case (WORD)X509_MULTI_BYTE_UINT:
3843 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3844 break;
3845 case (WORD)X509_ENUMERATED:
3846 decodeFunc = CRYPT_AsnDecodeEnumerated;
3847 break;
3848 case (WORD)X509_CHOICE_OF_TIME:
3849 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3850 break;
3851 case (WORD)X509_AUTHORITY_KEY_ID2:
3852 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
3853 break;
3854 case (WORD)PKCS_CONTENT_INFO:
3855 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
3856 break;
3857 case (WORD)X509_SEQUENCE_OF_ANY:
3858 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3859 break;
3860 case (WORD)PKCS_UTC_TIME:
3861 decodeFunc = CRYPT_AsnDecodeUtcTime;
3862 break;
3863 case (WORD)X509_CRL_DIST_POINTS:
3864 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3865 break;
3866 case (WORD)X509_ENHANCED_KEY_USAGE:
3867 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3868 break;
3869 case (WORD)PKCS_ATTRIBUTES:
3870 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
3871 break;
3872 case (WORD)X509_ISSUING_DIST_POINT:
3873 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3874 break;
3875 case (WORD)PKCS7_SIGNER_INFO:
3876 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
3877 break;
3878 default:
3879 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3882 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3883 decodeFunc = CRYPT_AsnDecodeExtensions;
3884 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3885 decodeFunc = CRYPT_AsnDecodeUtcTime;
3886 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3887 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3888 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3889 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
3890 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3891 decodeFunc = CRYPT_AsnDecodeEnumerated;
3892 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3893 decodeFunc = CRYPT_AsnDecodeBits;
3894 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3895 decodeFunc = CRYPT_AsnDecodeOctets;
3896 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3897 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3898 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3899 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3900 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3901 decodeFunc = CRYPT_AsnDecodeAltName;
3902 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3903 decodeFunc = CRYPT_AsnDecodeAltName;
3904 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3905 decodeFunc = CRYPT_AsnDecodeAltName;
3906 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3907 decodeFunc = CRYPT_AsnDecodeAltName;
3908 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3909 decodeFunc = CRYPT_AsnDecodeAltName;
3910 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3911 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3912 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3913 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3914 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3915 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3916 else
3917 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3918 debugstr_a(lpszStructType));
3919 if (!decodeFunc)
3921 if (!set)
3922 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
3923 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3924 (void **)&decodeFunc, &hFunc);
3926 if (decodeFunc)
3927 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3928 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3929 else
3930 SetLastError(ERROR_FILE_NOT_FOUND);
3931 if (hFunc)
3932 CryptFreeOIDFunctionAddress(hFunc, 0);
3933 return ret;