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.
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
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
39 #define NONAMELESSUNION
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "crypt32_private.h"
51 /* This is a bit arbitrary, but to set some limit: */
52 #define MAX_ENCODED_LEN 0x02000000
54 #define ASN_FLAGS_MASK 0xe0
55 #define ASN_TYPE_MASK 0x1f
57 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
65 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
66 DWORD, DWORD, void *, DWORD *);
67 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
68 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
70 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
71 * The dwCertEncodingType and lpszStructType are ignored by the built-in
72 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
73 * since it must call functions in external DLLs that follow these signatures.
75 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
77 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
78 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
80 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
81 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
82 * time, doesn't do memory allocation, and doesn't do exception handling.
83 * (This isn't intended to be the externally-called one.)
85 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
86 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
87 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
88 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
89 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
90 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
91 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
92 /* Internal function */
93 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
94 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
95 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
96 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
97 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
98 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
99 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
100 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
101 * member has been initialized, doesn't do exception handling, and doesn't do
104 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
105 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
106 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
107 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
108 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
109 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
110 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
111 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
112 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
113 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
114 * member has been initialized, doesn't do exception handling, and doesn't do
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;
132 CryptDecodeObjectFunc pCryptDecodeObject;
133 HCRYPTOIDFUNCADDR hFunc;
135 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType,
136 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
137 pvStructInfo, pcbStructInfo);
139 if (!pvStructInfo && !pcbStructInfo)
141 SetLastError(ERROR_INVALID_PARAMETER);
145 /* Try registered DLL first.. */
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);
158 /* If not, use CryptDecodeObjectEx */
159 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
160 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
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,
180 SetLastError(CRYPT_E_ASN1_CORRUPT);
183 else if (pbEncoded[1] <= 0x7f)
185 if (pbEncoded[1] + 1 > cbEncoded)
187 SetLastError(CRYPT_E_ASN1_EOD);
198 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
200 if (lenLen > sizeof(DWORD) + 1)
202 SetLastError(CRYPT_E_ASN1_LARGE);
205 else if (lenLen + 2 > cbEncoded)
207 SetLastError(CRYPT_E_ASN1_CORRUPT);
220 if (out + lenLen + 1 > cbEncoded)
222 SetLastError(CRYPT_E_ASN1_EOD);
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,
246 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
248 if (pDecodePara && pDecodePara->pfnAlloc)
249 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
251 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
252 if (!*(BYTE **)pvStructInfo)
255 *pcbStructInfo = bytesNeeded;
257 else if (*pcbStructInfo < bytesNeeded)
259 *pcbStructInfo = bytesNeeded;
260 SetLastError(ERROR_MORE_DATA);
267 * The expected tag of the item. If tag is 0, decodeFunc is called
268 * regardless of the tag value seen.
270 * A sequence is decoded into a struct. The offset member is the
271 * offset of this item within that struct.
273 * The decoder function to use. If this is NULL, then the member isn't
274 * decoded, but minSize space is reserved for it.
276 * The minimum amount of space occupied after decoding. You must set this.
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).
286 * Used by CRYPT_AsnDecodeSequence, not for your use.
288 struct AsnDecodeSequenceItem
292 CryptDecodeObjectExFunc decodeFunc;
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)
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)
315 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
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",
326 *(BYTE **)((BYTE *)pvStructInfo +
327 items[i].pointerOffset) = nextData;
329 if (items[i].decodeFunc)
332 TRACE("decoding item %ld\n", i);
334 TRACE("sizing item %ld\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);
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 %
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 %ld\n", i);
361 items[i].size = items[i].minSize;
362 SetLastError(NOERROR);
366 TRACE("item %ld failed: %08lx\n", i,
370 items[i].size = items[i].minSize;
372 else if (items[i].optional)
374 TRACE("skipping optional item %ld\n", i);
375 items[i].size = items[i].minSize;
379 TRACE("tag %02x doesn't match expected %02x\n",
380 ptr[0], items[i].tag);
381 SetLastError(CRYPT_E_ASN1_BADTAG);
386 else if (items[i].optional)
388 TRACE("missing optional item %ld, skipping\n", i);
389 items[i].size = items[i].minSize;
393 TRACE("not enough bytes for item %ld, failing\n", i);
394 SetLastError(CRYPT_E_ASN1_CORRUPT);
398 if (cbEncoded - (ptr - pbEncoded) != 0)
400 TRACE("%ld remaining bytes, failing\n", cbEncoded -
402 SetLastError(CRYPT_E_ASN1_CORRUPT);
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)
424 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded,
425 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
428 if (pbEncoded[0] == ASN_SEQUENCE)
432 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
436 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
437 cbEncoded, dwFlags, NULL, NULL);
440 DWORD bytesNeeded = 0, structSize = 0;
442 for (i = 0; i < cItem; i++)
444 bytesNeeded += items[i].size;
445 structSize += items[i].minSize;
448 *pcbStructInfo = bytesNeeded;
449 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
450 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
454 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
455 pvStructInfo = *(BYTE **)pvStructInfo;
457 nextData = (BYTE *)startingPointer;
459 nextData = (BYTE *)pvStructInfo + structSize;
460 memset(pvStructInfo, 0, structSize);
461 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
462 pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
469 SetLastError(CRYPT_E_ASN1_BADTAG);
472 TRACE("returning %d (%08lx)\n", ret, GetLastError());
477 * The expected tag of the entire encoded array (usually a variant
478 * of ASN_SETOF or ASN_SEQUENCEOF.)
480 * used to decode each item in the array
482 * is the minimum size of each decoded item
484 * indicates whether each item has a dynamic pointer
486 * indicates the offset within itemSize at which the pointer exists
488 struct AsnArrayDescriptor
491 CryptDecodeObjectExFunc decodeFunc;
497 struct AsnArrayItemSize
503 /* Decodes an array of like types into a struct GenericArray.
504 * The layout and decoding of the array are described by a struct
505 * AsnArrayDescriptor.
507 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
508 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
509 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
510 void *startingPointer)
514 TRACE("%p, %p, %ld, %08lx, %p, %p, %ld, %p\n", arrayDesc, pbEncoded,
515 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
518 if (pbEncoded[0] == arrayDesc->tag)
522 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
524 DWORD bytesNeeded, cItems = 0;
525 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
526 /* There can be arbitrarily many items, but there is often only one.
528 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
530 bytesNeeded = sizeof(struct GenericArray);
535 for (ptr = pbEncoded + 1 + lenBytes; ret &&
536 ptr - pbEncoded - 1 - lenBytes < dataLen; )
538 DWORD itemLenBytes, itemDataLen, size;
540 itemLenBytes = GET_LEN_BYTES(ptr[1]);
541 /* Each item decoded may not tolerate extraneous bytes, so
542 * get the length of the next element and pass it directly.
544 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
547 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
548 1 + itemLenBytes + itemDataLen,
549 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
556 if (itemSizes != &itemSize)
557 itemSizes = CryptMemRealloc(itemSizes,
558 cItems * sizeof(struct AsnArrayItemSize));
563 cItems * sizeof(struct AsnArrayItemSize));
565 memcpy(itemSizes, &itemSize, sizeof(itemSize));
569 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
571 itemSizes[cItems - 1].size = size;
573 ret = CRYPT_GetLen(ptr,
574 cbEncoded - (ptr - pbEncoded), &nextLen);
576 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
586 *pcbStructInfo = bytesNeeded;
587 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
588 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
593 struct GenericArray *array;
595 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
596 pvStructInfo = *(BYTE **)pvStructInfo;
597 array = (struct GenericArray *)pvStructInfo;
598 array->cItems = cItems;
600 array->rgItems = startingPointer;
602 array->rgItems = (BYTE *)array +
603 sizeof(struct GenericArray);
604 nextData = (BYTE *)array->rgItems +
605 array->cItems * arrayDesc->itemSize;
606 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
607 i < cItems && ptr - pbEncoded - 1 - lenBytes <
610 if (arrayDesc->hasPointer)
611 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
612 + arrayDesc->pointerOffset) = nextData;
613 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
614 itemSizes[i].encodedLen,
615 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
616 array->rgItems + i * arrayDesc->itemSize,
622 nextData += itemSizes[i].size - arrayDesc->itemSize;
623 ret = CRYPT_GetLen(ptr,
624 cbEncoded - (ptr - pbEncoded), &nextLen);
626 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
631 if (itemSizes != &itemSize)
632 CryptMemFree(itemSizes);
637 SetLastError(CRYPT_E_ASN1_BADTAG);
643 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
644 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
645 * to CRYPT_E_ASN1_CORRUPT.
646 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
649 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
650 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
651 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
656 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
658 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
659 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
661 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
662 bytesNeeded += 1 + lenBytes + dataLen;
665 *pcbStructInfo = bytesNeeded;
666 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
667 pvStructInfo, pcbStructInfo, bytesNeeded)))
669 CRYPT_DER_BLOB *blob;
671 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
672 pvStructInfo = *(BYTE **)pvStructInfo;
673 blob = (CRYPT_DER_BLOB *)pvStructInfo;
674 blob->cbData = 1 + lenBytes + dataLen;
677 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
678 blob->pbData = (BYTE *)pbEncoded;
681 assert(blob->pbData);
682 memcpy(blob->pbData, pbEncoded, blob->cbData);
687 SetLastError(CRYPT_E_ASN1_CORRUPT);
695 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
696 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
697 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
698 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
702 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
703 pDecodePara, pvStructInfo, *pcbStructInfo);
705 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
708 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
709 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
710 pvStructInfo, pcbStructInfo);
711 if (ret && pvStructInfo)
713 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
720 for (i = 0; i < blob->cbData / 2; i++)
722 temp = blob->pbData[i];
723 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
724 blob->pbData[blob->cbData - i - 1] = temp;
728 TRACE("returning %d (%08lx)\n", ret, GetLastError());
732 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
733 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
734 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
738 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
739 pDecodePara, pvStructInfo, *pcbStructInfo);
743 struct AsnDecodeSequenceItem items[] = {
744 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
745 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
746 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
747 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
748 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
749 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
750 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
751 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
752 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
753 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
756 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
757 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
758 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
759 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
760 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
764 SetLastError(STATUS_ACCESS_VIOLATION);
769 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
773 /* Internal function */
774 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
775 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
776 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
781 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
783 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
785 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
786 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
787 pvStructInfo, pcbStructInfo);
792 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
793 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
794 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
798 struct AsnDecodeSequenceItem items[] = {
799 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
800 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
801 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
802 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
805 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
806 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
807 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
811 /* Internal function */
812 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
813 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
814 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
819 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
821 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
823 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
824 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
825 pDecodePara, pvStructInfo, pcbStructInfo);
830 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
831 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
832 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
835 struct AsnDecodeSequenceItem items[] = {
836 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
837 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
838 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
839 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
840 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
841 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
842 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
843 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
844 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
845 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
847 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
848 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
850 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
851 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
853 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
854 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
855 FALSE, TRUE, offsetof(CERT_INFO,
856 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
857 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
858 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
859 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
860 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
861 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
862 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
863 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
864 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
865 offsetof(CERT_INFO, rgExtension), 0 },
868 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
869 pDecodePara, pvStructInfo, *pcbStructInfo);
871 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
872 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
873 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
875 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
879 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
880 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
881 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
885 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
886 pDecodePara, pvStructInfo, *pcbStructInfo);
890 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
893 /* First try to decode it as a signed cert. */
894 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
895 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
896 (BYTE *)&signedCert, &size);
900 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
901 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
902 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
904 LocalFree(signedCert);
906 /* Failing that, try it as an unsigned cert */
910 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
911 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
912 pDecodePara, pvStructInfo, pcbStructInfo);
917 SetLastError(STATUS_ACCESS_VIOLATION);
922 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
926 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
927 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
928 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
931 struct AsnDecodeSequenceItem items[] = {
932 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
933 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
934 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
935 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
936 sizeof(FILETIME), FALSE, FALSE, 0 },
937 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
938 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
939 offsetof(CRL_ENTRY, rgExtension), 0 },
941 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
943 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
946 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
947 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
948 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
952 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
953 * been set prior to calling.
955 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
956 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
957 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
960 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
961 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
962 offsetof(CRL_ENTRY, SerialNumber.pbData) };
963 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
965 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
966 pDecodePara, pvStructInfo, *pcbStructInfo);
968 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
969 pDecodePara, pvStructInfo, pcbStructInfo,
970 entries ? entries->rgItems : NULL);
971 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
975 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
976 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
977 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
979 struct AsnDecodeSequenceItem items[] = {
980 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
981 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
982 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
983 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
984 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
985 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
986 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
988 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
989 sizeof(FILETIME), FALSE, FALSE, 0 },
990 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
991 sizeof(FILETIME), TRUE, FALSE, 0 },
992 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
993 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
994 offsetof(CRL_INFO, rgCRLEntry), 0 },
995 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
996 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
997 offsetof(CRL_INFO, rgExtension), 0 },
1001 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1002 pDecodePara, pvStructInfo, *pcbStructInfo);
1004 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1005 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1006 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1008 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1012 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1013 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1014 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1018 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1019 pDecodePara, pvStructInfo, *pcbStructInfo);
1023 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1026 /* First try to decode it as a signed crl. */
1027 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1028 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1029 (BYTE *)&signedCrl, &size);
1033 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1034 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1035 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1036 pvStructInfo, pcbStructInfo);
1037 LocalFree(signedCrl);
1039 /* Failing that, try it as an unsigned crl */
1043 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1044 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1045 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1050 SetLastError(STATUS_ACCESS_VIOLATION);
1055 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1059 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1060 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1061 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1065 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1066 pDecodePara, pvStructInfo, *pcbStructInfo);
1068 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1072 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1074 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1075 DWORD bytesNeeded = sizeof(LPSTR);
1079 /* The largest possible string for the first two components
1080 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1085 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1086 pbEncoded[1 + lenBytes] / 40,
1087 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1089 bytesNeeded += strlen(firstTwo) + 1;
1090 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1091 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1093 /* large enough for ".4000000" */
1097 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1104 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1107 SetLastError(CRYPT_E_ASN1_CORRUPT);
1114 snprintf(str, sizeof(str), ".%d", val);
1115 bytesNeeded += strlen(str);
1120 *pcbStructInfo = bytesNeeded;
1121 else if (*pcbStructInfo < bytesNeeded)
1123 *pcbStructInfo = bytesNeeded;
1124 SetLastError(ERROR_MORE_DATA);
1132 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1135 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1136 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1138 pszObjId += strlen(pszObjId);
1139 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1140 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1144 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1153 sprintf(pszObjId, ".%d", val);
1154 pszObjId += strlen(pszObjId);
1158 *(LPSTR *)pvStructInfo = NULL;
1159 *pcbStructInfo = bytesNeeded;
1166 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1169 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1170 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1171 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1173 struct AsnDecodeSequenceItem items[] = {
1174 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1175 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1176 offsetof(CERT_EXTENSION, pszObjId), 0 },
1177 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1178 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1179 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1180 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1181 offsetof(CERT_EXTENSION, Value.pbData) },
1184 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1186 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
1190 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1191 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1192 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1193 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1195 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1196 debugstr_a(ext->pszObjId));
1197 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1201 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1202 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1203 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1206 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1207 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1208 offsetof(CERT_EXTENSION, pszObjId) };
1209 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1211 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1212 pDecodePara, pvStructInfo, *pcbStructInfo);
1214 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1215 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1219 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1220 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1221 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1227 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1228 lpszStructType, pbEncoded, cbEncoded,
1229 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1230 if (ret && pvStructInfo)
1232 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1233 pcbStructInfo, *pcbStructInfo);
1236 CERT_EXTENSIONS *exts;
1238 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1239 pvStructInfo = *(BYTE **)pvStructInfo;
1240 exts = (CERT_EXTENSIONS *)pvStructInfo;
1241 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1242 sizeof(CERT_EXTENSIONS));
1243 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1244 lpszStructType, pbEncoded, cbEncoded,
1245 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1252 SetLastError(STATUS_ACCESS_VIOLATION);
1259 /* Warning: this assumes the address of value->Value.pbData is already set, in
1260 * order to avoid overwriting memory. (In some cases, it may change it, if it
1261 * doesn't copy anything to memory.) Be sure to set it correctly!
1263 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1264 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1265 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1269 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1271 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1273 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1275 switch (pbEncoded[0])
1277 case ASN_NUMERICSTRING:
1278 case ASN_PRINTABLESTRING:
1283 FIXME("Unimplemented string type %02x\n", pbEncoded[0]);
1284 SetLastError(OSS_UNIMPLEMENTED);
1289 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE);
1291 switch (pbEncoded[0])
1293 case ASN_NUMERICSTRING:
1294 case ASN_PRINTABLESTRING:
1297 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1298 bytesNeeded += dataLen;
1302 *pcbStructInfo = bytesNeeded;
1303 else if (*pcbStructInfo < bytesNeeded)
1305 *pcbStructInfo = bytesNeeded;
1306 SetLastError(ERROR_MORE_DATA);
1311 *pcbStructInfo = bytesNeeded;
1312 switch (pbEncoded[0])
1314 case ASN_NUMERICSTRING:
1315 value->dwValueType = CERT_RDN_NUMERIC_STRING;
1317 case ASN_PRINTABLESTRING:
1318 value->dwValueType = CERT_RDN_PRINTABLE_STRING;
1321 value->dwValueType = CERT_RDN_IA5_STRING;
1324 value->dwValueType = CERT_RDN_T61_STRING;
1329 switch (pbEncoded[0])
1331 case ASN_NUMERICSTRING:
1332 case ASN_PRINTABLESTRING:
1335 value->Value.cbData = dataLen;
1336 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1337 value->Value.pbData = (BYTE *)pbEncoded + 1 +
1341 assert(value->Value.pbData);
1342 memcpy(value->Value.pbData,
1343 pbEncoded + 1 + lenBytes, dataLen);
1350 value->Value.cbData = 0;
1351 value->Value.pbData = NULL;
1359 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1360 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1361 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1367 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1368 lpszStructType, pbEncoded, cbEncoded,
1369 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1370 if (ret && pvStructInfo)
1372 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1373 pcbStructInfo, *pcbStructInfo);
1376 CERT_NAME_VALUE *value;
1378 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1379 pvStructInfo = *(BYTE **)pvStructInfo;
1380 value = (CERT_NAME_VALUE *)pvStructInfo;
1381 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1382 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1383 lpszStructType, pbEncoded, cbEncoded,
1384 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1391 SetLastError(STATUS_ACCESS_VIOLATION);
1398 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1399 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1400 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1403 struct AsnDecodeSequenceItem items[] = {
1404 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1405 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1406 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1407 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1408 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1409 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1411 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1413 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1414 pvStructInfo, *pcbStructInfo);
1417 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1418 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1419 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1420 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1423 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1424 debugstr_a(attr->pszObjId));
1425 TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1427 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1431 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1432 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1433 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1436 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1437 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1438 offsetof(CERT_RDN_ATTR, pszObjId) };
1439 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1441 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1442 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1446 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1447 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1448 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1454 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1455 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1456 offsetof(CERT_RDN, rgRDNAttr) };
1458 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1459 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1463 SetLastError(STATUS_ACCESS_VIOLATION);
1470 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1471 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1472 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1475 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1477 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1478 pDecodePara, pvStructInfo, *pcbStructInfo);
1480 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1481 bytesNeeded += cbEncoded;
1483 *pcbStructInfo = bytesNeeded;
1484 else if (*pcbStructInfo < bytesNeeded)
1486 SetLastError(ERROR_MORE_DATA);
1487 *pcbStructInfo = bytesNeeded;
1492 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1494 *pcbStructInfo = bytesNeeded;
1495 blob->cbData = cbEncoded;
1496 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1497 blob->pbData = (LPBYTE)pbEncoded;
1500 assert(blob->pbData);
1501 memcpy(blob->pbData, pbEncoded, blob->cbData);
1507 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1508 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1509 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1511 CRYPT_ALGORITHM_IDENTIFIER *algo =
1512 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1514 struct AsnDecodeSequenceItem items[] = {
1515 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1516 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1517 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1518 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1519 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1520 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1523 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1524 pDecodePara, pvStructInfo, *pcbStructInfo);
1526 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1527 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1528 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1529 if (ret && pvStructInfo)
1531 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1532 debugstr_a(algo->pszObjId));
1537 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1538 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1539 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1542 struct AsnDecodeSequenceItem items[] = {
1543 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1544 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1545 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1546 Algorithm.pszObjId) },
1547 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1548 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1549 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1551 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1553 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1554 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1555 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1556 info->Algorithm.Parameters.pbData : NULL);
1560 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1561 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1562 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1570 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1571 lpszStructType, pbEncoded, cbEncoded,
1572 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1575 *pcbStructInfo = bytesNeeded;
1576 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1577 pvStructInfo, pcbStructInfo, bytesNeeded)))
1579 PCERT_PUBLIC_KEY_INFO info;
1581 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1582 pvStructInfo = *(BYTE **)pvStructInfo;
1583 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1584 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
1585 sizeof(CERT_PUBLIC_KEY_INFO);
1586 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1587 lpszStructType, pbEncoded, cbEncoded,
1588 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1595 SetLastError(STATUS_ACCESS_VIOLATION);
1602 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
1603 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1604 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1610 SetLastError(CRYPT_E_ASN1_CORRUPT);
1613 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
1615 SetLastError(CRYPT_E_ASN1_CORRUPT);
1618 if (pbEncoded[1] > 1)
1620 SetLastError(CRYPT_E_ASN1_CORRUPT);
1625 *pcbStructInfo = sizeof(BOOL);
1628 else if (*pcbStructInfo < sizeof(BOOL))
1630 *pcbStructInfo = sizeof(BOOL);
1631 SetLastError(ERROR_MORE_DATA);
1636 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
1639 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1643 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
1644 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1645 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1647 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
1648 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
1651 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1652 pDecodePara, pvStructInfo, *pcbStructInfo);
1656 SetLastError(CRYPT_E_ASN1_CORRUPT);
1659 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
1661 SetLastError(CRYPT_E_ASN1_BADTAG);
1664 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1665 if (1 + lenBytes > cbEncoded)
1667 SetLastError(CRYPT_E_ASN1_CORRUPT);
1670 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1672 switch (pbEncoded[0] & ASN_TYPE_MASK)
1674 case 1: /* rfc822Name */
1675 case 2: /* dNSName */
1676 case 6: /* uniformResourceIdentifier */
1677 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1679 case 7: /* iPAddress */
1680 bytesNeeded += dataLen;
1682 case 8: /* registeredID */
1683 /* FIXME: decode as OID */
1684 case 0: /* otherName */
1685 case 4: /* directoryName */
1687 SetLastError(CRYPT_E_ASN1_BADTAG);
1690 case 3: /* x400Address, unimplemented */
1691 case 5: /* ediPartyName, unimplemented */
1692 SetLastError(CRYPT_E_ASN1_BADTAG);
1696 SetLastError(CRYPT_E_ASN1_CORRUPT);
1702 *pcbStructInfo = bytesNeeded;
1703 else if (*pcbStructInfo < bytesNeeded)
1705 *pcbStructInfo = bytesNeeded;
1706 SetLastError(ERROR_MORE_DATA);
1711 *pcbStructInfo = bytesNeeded;
1712 /* MS used values one greater than the asn1 ones.. sigh */
1713 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
1714 switch (pbEncoded[0] & ASN_TYPE_MASK)
1716 case 1: /* rfc822Name */
1717 case 2: /* dNSName */
1718 case 6: /* uniformResourceIdentifier */
1722 for (i = 0; i < dataLen; i++)
1723 entry->u.pwszURL[i] =
1724 (WCHAR)pbEncoded[1 + lenBytes + i];
1725 entry->u.pwszURL[i] = 0;
1726 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
1727 debugstr_w(entry->u.pwszURL));
1730 case 7: /* iPAddress */
1731 /* The next data pointer is in the pwszURL spot, that is,
1732 * the first 4 bytes. Need to move it to the next spot.
1734 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
1735 entry->u.IPAddress.cbData = dataLen;
1736 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
1746 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
1747 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1748 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1751 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1752 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
1753 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
1754 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
1756 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1757 pDecodePara, pvStructInfo, *pcbStructInfo);
1760 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
1761 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1762 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
1766 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
1767 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1768 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1772 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1773 pDecodePara, pvStructInfo, *pcbStructInfo);
1777 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1778 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
1779 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
1781 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1782 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1786 SetLastError(STATUS_ACCESS_VIOLATION);
1793 struct PATH_LEN_CONSTRAINT
1795 BOOL fPathLenConstraint;
1796 DWORD dwPathLenConstraint;
1799 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
1800 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1801 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1805 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1806 pvStructInfo, *pcbStructInfo);
1810 if (pbEncoded[0] == ASN_INTEGER)
1812 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
1815 *pcbStructInfo = bytesNeeded;
1816 else if (*pcbStructInfo < bytesNeeded)
1818 SetLastError(ERROR_MORE_DATA);
1819 *pcbStructInfo = bytesNeeded;
1824 struct PATH_LEN_CONSTRAINT *constraint =
1825 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
1826 DWORD size = sizeof(constraint->dwPathLenConstraint);
1828 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
1829 pbEncoded, cbEncoded, 0, NULL,
1830 &constraint->dwPathLenConstraint, &size);
1832 constraint->fPathLenConstraint = TRUE;
1833 TRACE("got an int, dwPathLenConstraint is %ld\n",
1834 constraint->dwPathLenConstraint);
1839 SetLastError(CRYPT_E_ASN1_CORRUPT);
1843 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1847 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
1848 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1849 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1852 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1853 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
1854 offsetof(CERT_NAME_BLOB, pbData) };
1855 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1857 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1858 pDecodePara, pvStructInfo, *pcbStructInfo);
1860 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1861 pDecodePara, pvStructInfo, pcbStructInfo,
1862 entries ? entries->rgItems : NULL);
1863 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1867 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
1868 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1869 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1875 struct AsnDecodeSequenceItem items[] = {
1876 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
1877 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1878 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
1879 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
1880 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
1881 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
1882 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
1883 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
1884 sizeof(struct GenericArray), TRUE, TRUE,
1885 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
1888 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1889 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1890 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1894 SetLastError(STATUS_ACCESS_VIOLATION);
1901 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
1902 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1903 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1909 struct AsnDecodeSequenceItem items[] = {
1910 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
1911 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
1912 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
1913 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
1914 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
1917 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1918 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1919 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1923 SetLastError(STATUS_ACCESS_VIOLATION);
1930 #define RSA1_MAGIC 0x31415352
1932 struct DECODED_RSA_PUB_KEY
1935 CRYPT_INTEGER_BLOB modulus;
1938 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
1939 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1940 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1946 struct AsnDecodeSequenceItem items[] = {
1947 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
1948 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
1949 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
1951 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
1952 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
1954 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
1957 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1958 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
1959 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
1962 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1963 decodedKey->modulus.cbData;
1967 *pcbStructInfo = bytesNeeded;
1970 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1971 pvStructInfo, pcbStructInfo, bytesNeeded)))
1974 RSAPUBKEY *rsaPubKey;
1976 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1977 pvStructInfo = *(BYTE **)pvStructInfo;
1978 hdr = (BLOBHEADER *)pvStructInfo;
1979 hdr->bType = PUBLICKEYBLOB;
1980 hdr->bVersion = CUR_BLOB_VERSION;
1982 hdr->aiKeyAlg = CALG_RSA_KEYX;
1983 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
1984 sizeof(BLOBHEADER));
1985 rsaPubKey->magic = RSA1_MAGIC;
1986 rsaPubKey->pubexp = decodedKey->pubexp;
1987 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
1988 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
1989 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
1990 decodedKey->modulus.cbData);
1992 LocalFree(decodedKey);
1997 SetLastError(STATUS_ACCESS_VIOLATION);
2004 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2005 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2006 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2009 DWORD bytesNeeded, dataLen;
2011 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2012 pDecodePara, pvStructInfo, *pcbStructInfo);
2014 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2016 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2017 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2019 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2021 *pcbStructInfo = bytesNeeded;
2022 else if (*pcbStructInfo < bytesNeeded)
2024 SetLastError(ERROR_MORE_DATA);
2025 *pcbStructInfo = bytesNeeded;
2030 CRYPT_DATA_BLOB *blob;
2031 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2033 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2034 blob->cbData = dataLen;
2035 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2036 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2039 assert(blob->pbData);
2041 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2049 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2050 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2051 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2055 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2056 pDecodePara, pvStructInfo, *pcbStructInfo);
2064 SetLastError(CRYPT_E_ASN1_CORRUPT);
2067 else if (pbEncoded[0] != ASN_OCTETSTRING)
2069 SetLastError(CRYPT_E_ASN1_BADTAG);
2072 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2073 lpszStructType, pbEncoded, cbEncoded,
2074 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2077 *pcbStructInfo = bytesNeeded;
2078 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2079 pvStructInfo, pcbStructInfo, bytesNeeded)))
2081 CRYPT_DATA_BLOB *blob;
2083 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2084 pvStructInfo = *(BYTE **)pvStructInfo;
2085 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2086 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2087 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2088 lpszStructType, pbEncoded, cbEncoded,
2089 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2096 SetLastError(STATUS_ACCESS_VIOLATION);
2103 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2104 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2105 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2109 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2110 pDecodePara, pvStructInfo, *pcbStructInfo);
2112 if (pbEncoded[0] == ASN_BITSTRING)
2114 DWORD bytesNeeded, dataLen;
2116 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2118 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2119 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2121 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2123 *pcbStructInfo = bytesNeeded;
2124 else if (*pcbStructInfo < bytesNeeded)
2126 *pcbStructInfo = bytesNeeded;
2127 SetLastError(ERROR_MORE_DATA);
2132 CRYPT_BIT_BLOB *blob;
2134 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2135 blob->cbData = dataLen - 1;
2136 blob->cUnusedBits = *(pbEncoded + 1 +
2137 GET_LEN_BYTES(pbEncoded[1]));
2138 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2140 blob->pbData = (BYTE *)pbEncoded + 2 +
2141 GET_LEN_BYTES(pbEncoded[1]);
2145 assert(blob->pbData);
2148 BYTE mask = 0xff << blob->cUnusedBits;
2150 memcpy(blob->pbData, pbEncoded + 2 +
2151 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2152 blob->pbData[blob->cbData - 1] &= mask;
2160 SetLastError(CRYPT_E_ASN1_BADTAG);
2163 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2167 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2168 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2169 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2173 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2174 pDecodePara, pvStructInfo, pcbStructInfo);
2180 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2181 lpszStructType, pbEncoded, cbEncoded,
2182 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2185 *pcbStructInfo = bytesNeeded;
2186 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2187 pvStructInfo, pcbStructInfo, bytesNeeded)))
2189 CRYPT_BIT_BLOB *blob;
2191 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2192 pvStructInfo = *(BYTE **)pvStructInfo;
2193 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2194 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2195 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2196 lpszStructType, pbEncoded, cbEncoded,
2197 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2204 SetLastError(STATUS_ACCESS_VIOLATION);
2208 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2212 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2213 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2214 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2220 *pcbStructInfo = sizeof(int);
2225 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2226 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2227 DWORD size = sizeof(buf);
2229 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2230 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2231 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size);
2234 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2235 pvStructInfo, pcbStructInfo, sizeof(int))))
2239 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2240 pvStructInfo = *(BYTE **)pvStructInfo;
2241 if (blob->pbData[blob->cbData - 1] & 0x80)
2243 /* initialize to a negative value to sign-extend */
2248 for (i = 0; i < blob->cbData; i++)
2251 val |= blob->pbData[blob->cbData - i - 1];
2253 memcpy(pvStructInfo, &val, sizeof(int));
2256 else if (GetLastError() == ERROR_MORE_DATA)
2257 SetLastError(CRYPT_E_ASN1_LARGE);
2261 SetLastError(STATUS_ACCESS_VIOLATION);
2268 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2269 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2270 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2274 if (pbEncoded[0] == ASN_INTEGER)
2276 DWORD bytesNeeded, dataLen;
2278 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2280 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2282 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2284 *pcbStructInfo = bytesNeeded;
2285 else if (*pcbStructInfo < bytesNeeded)
2287 *pcbStructInfo = bytesNeeded;
2288 SetLastError(ERROR_MORE_DATA);
2293 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2295 blob->cbData = dataLen;
2296 assert(blob->pbData);
2301 for (i = 0; i < blob->cbData; i++)
2303 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2312 SetLastError(CRYPT_E_ASN1_BADTAG);
2318 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2319 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2320 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2328 if ((ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2329 lpszStructType, pbEncoded, cbEncoded,
2330 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2333 *pcbStructInfo = bytesNeeded;
2334 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2335 pvStructInfo, pcbStructInfo, bytesNeeded)))
2337 CRYPT_INTEGER_BLOB *blob;
2339 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2340 pvStructInfo = *(BYTE **)pvStructInfo;
2341 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2342 blob->pbData = (BYTE *)pvStructInfo +
2343 sizeof(CRYPT_INTEGER_BLOB);
2344 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2345 lpszStructType, pbEncoded, cbEncoded,
2346 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2353 SetLastError(STATUS_ACCESS_VIOLATION);
2360 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
2361 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2362 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2363 void *pvStructInfo, DWORD *pcbStructInfo)
2367 if (pbEncoded[0] == ASN_INTEGER)
2369 DWORD bytesNeeded, dataLen;
2371 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2373 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2375 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2377 *pcbStructInfo = bytesNeeded;
2378 else if (*pcbStructInfo < bytesNeeded)
2380 *pcbStructInfo = bytesNeeded;
2381 SetLastError(ERROR_MORE_DATA);
2386 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2388 blob->cbData = dataLen;
2389 assert(blob->pbData);
2390 /* remove leading zero byte if it exists */
2391 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2400 for (i = 0; i < blob->cbData; i++)
2402 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2411 SetLastError(CRYPT_E_ASN1_BADTAG);
2417 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2418 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2419 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2427 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2428 lpszStructType, pbEncoded, cbEncoded,
2429 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2432 *pcbStructInfo = bytesNeeded;
2433 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2434 pvStructInfo, pcbStructInfo, bytesNeeded)))
2436 CRYPT_INTEGER_BLOB *blob;
2438 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2439 pvStructInfo = *(BYTE **)pvStructInfo;
2440 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2441 blob->pbData = (BYTE *)pvStructInfo +
2442 sizeof(CRYPT_INTEGER_BLOB);
2443 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2444 lpszStructType, pbEncoded, cbEncoded,
2445 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2452 SetLastError(STATUS_ACCESS_VIOLATION);
2459 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
2460 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2461 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2467 *pcbStructInfo = sizeof(int);
2472 if (pbEncoded[0] == ASN_ENUMERATED)
2474 unsigned int val = 0, i;
2478 SetLastError(CRYPT_E_ASN1_EOD);
2481 else if (pbEncoded[1] == 0)
2483 SetLastError(CRYPT_E_ASN1_CORRUPT);
2488 /* A little strange looking, but we have to accept a sign byte:
2489 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
2490 * assuming a small length is okay here, it has to be in short
2493 if (pbEncoded[1] > sizeof(unsigned int) + 1)
2495 SetLastError(CRYPT_E_ASN1_LARGE);
2498 for (i = 0; i < pbEncoded[1]; i++)
2501 val |= pbEncoded[2 + i];
2503 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2504 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
2506 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2507 pvStructInfo = *(BYTE **)pvStructInfo;
2508 memcpy(pvStructInfo, &val, sizeof(unsigned int));
2514 SetLastError(CRYPT_E_ASN1_BADTAG);
2520 SetLastError(STATUS_ACCESS_VIOLATION);
2527 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
2530 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
2535 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
2537 if (!isdigit(*(pbEncoded))) \
2539 SetLastError(CRYPT_E_ASN1_CORRUPT); \
2545 (word) += *(pbEncoded)++ - '0'; \
2550 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
2551 SYSTEMTIME *sysTime)
2558 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
2560 WORD hours, minutes = 0;
2561 BYTE sign = *pbEncoded++;
2564 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
2565 if (ret && hours >= 24)
2567 SetLastError(CRYPT_E_ASN1_CORRUPT);
2572 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
2573 if (ret && minutes >= 60)
2575 SetLastError(CRYPT_E_ASN1_CORRUPT);
2583 sysTime->wHour += hours;
2584 sysTime->wMinute += minutes;
2588 if (hours > sysTime->wHour)
2591 sysTime->wHour = 24 - (hours - sysTime->wHour);
2594 sysTime->wHour -= hours;
2595 if (minutes > sysTime->wMinute)
2598 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
2601 sysTime->wMinute -= minutes;
2608 SetLastError(STATUS_ACCESS_VIOLATION);
2615 #define MIN_ENCODED_TIME_LENGTH 10
2617 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
2618 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2619 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2625 *pcbStructInfo = sizeof(FILETIME);
2631 if (pbEncoded[0] == ASN_UTCTIME)
2635 SetLastError(CRYPT_E_ASN1_EOD);
2638 else if (pbEncoded[1] > 0x7f)
2640 /* long-form date strings really can't be valid */
2641 SetLastError(CRYPT_E_ASN1_CORRUPT);
2646 SYSTEMTIME sysTime = { 0 };
2647 BYTE len = pbEncoded[1];
2649 if (len < MIN_ENCODED_TIME_LENGTH)
2651 SetLastError(CRYPT_E_ASN1_CORRUPT);
2657 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
2658 if (sysTime.wYear >= 50)
2659 sysTime.wYear += 1900;
2661 sysTime.wYear += 2000;
2662 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2663 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2664 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2665 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
2668 if (len >= 2 && isdigit(*pbEncoded) &&
2669 isdigit(*(pbEncoded + 1)))
2670 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2672 else if (isdigit(*pbEncoded))
2673 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
2676 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2679 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2680 pDecodePara, pvStructInfo, pcbStructInfo,
2683 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2684 pvStructInfo = *(BYTE **)pvStructInfo;
2685 ret = SystemTimeToFileTime(&sysTime,
2686 (FILETIME *)pvStructInfo);
2693 SetLastError(CRYPT_E_ASN1_BADTAG);
2699 SetLastError(STATUS_ACCESS_VIOLATION);
2706 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
2707 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2708 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2714 *pcbStructInfo = sizeof(FILETIME);
2720 if (pbEncoded[0] == ASN_GENERALTIME)
2724 SetLastError(CRYPT_E_ASN1_EOD);
2727 else if (pbEncoded[1] > 0x7f)
2729 /* long-form date strings really can't be valid */
2730 SetLastError(CRYPT_E_ASN1_CORRUPT);
2735 BYTE len = pbEncoded[1];
2737 if (len < MIN_ENCODED_TIME_LENGTH)
2739 SetLastError(CRYPT_E_ASN1_CORRUPT);
2744 SYSTEMTIME sysTime = { 0 };
2747 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
2748 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2749 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2750 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2753 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2756 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2758 if (ret && len > 0 && (*pbEncoded == '.' ||
2765 /* workaround macro weirdness */
2766 digits = min(len, 3);
2767 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
2768 sysTime.wMilliseconds);
2771 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2774 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2775 pDecodePara, pvStructInfo, pcbStructInfo,
2778 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2779 pvStructInfo = *(BYTE **)pvStructInfo;
2780 ret = SystemTimeToFileTime(&sysTime,
2781 (FILETIME *)pvStructInfo);
2788 SetLastError(CRYPT_E_ASN1_BADTAG);
2794 SetLastError(STATUS_ACCESS_VIOLATION);
2801 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
2802 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2803 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2809 if (pbEncoded[0] == ASN_UTCTIME)
2810 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
2811 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2813 else if (pbEncoded[0] == ASN_GENERALTIME)
2814 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
2815 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
2816 pvStructInfo, pcbStructInfo);
2819 SetLastError(CRYPT_E_ASN1_BADTAG);
2825 SetLastError(STATUS_ACCESS_VIOLATION);
2832 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
2833 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2834 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2840 if (pbEncoded[0] == ASN_SEQUENCEOF)
2842 DWORD bytesNeeded, dataLen, remainingLen, cValue;
2844 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2849 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2850 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
2852 ptr = pbEncoded + 1 + lenBytes;
2853 remainingLen = dataLen;
2854 while (ret && remainingLen)
2858 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
2861 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
2863 remainingLen -= 1 + nextLenBytes + nextLen;
2864 ptr += 1 + nextLenBytes + nextLen;
2865 bytesNeeded += sizeof(CRYPT_DER_BLOB);
2866 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2867 bytesNeeded += 1 + nextLenBytes + nextLen;
2873 CRYPT_SEQUENCE_OF_ANY *seq;
2877 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2878 pvStructInfo, pcbStructInfo, bytesNeeded)))
2880 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2881 pvStructInfo = *(BYTE **)pvStructInfo;
2882 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2883 seq->cValue = cValue;
2884 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
2886 nextPtr = (BYTE *)seq->rgValue +
2887 cValue * sizeof(CRYPT_DER_BLOB);
2888 ptr = pbEncoded + 1 + lenBytes;
2889 remainingLen = dataLen;
2891 while (ret && remainingLen)
2895 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
2898 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
2900 seq->rgValue[i].cbData = 1 + nextLenBytes +
2902 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2903 seq->rgValue[i].pbData = (BYTE *)ptr;
2906 seq->rgValue[i].pbData = nextPtr;
2907 memcpy(nextPtr, ptr, 1 + nextLenBytes +
2909 nextPtr += 1 + nextLenBytes + nextLen;
2911 remainingLen -= 1 + nextLenBytes + nextLen;
2912 ptr += 1 + nextLenBytes + nextLen;
2922 SetLastError(CRYPT_E_ASN1_BADTAG);
2928 SetLastError(STATUS_ACCESS_VIOLATION);
2935 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
2936 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2937 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2941 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
2943 DWORD bytesNeeded, dataLen;
2945 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2947 struct AsnArrayDescriptor arrayDesc = {
2948 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
2949 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2950 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2951 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2957 ret = CRYPT_AsnDecodeArray(&arrayDesc,
2958 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
2959 0, NULL, NULL, &nameLen, NULL);
2960 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
2963 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
2965 *pcbStructInfo = bytesNeeded;
2966 else if (*pcbStructInfo < bytesNeeded)
2968 *pcbStructInfo = bytesNeeded;
2969 SetLastError(ERROR_MORE_DATA);
2974 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
2978 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2979 ret = CRYPT_AsnDecodeArray(&arrayDesc,
2980 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
2981 0, NULL, &name->u.FullName, pcbStructInfo,
2982 name->u.FullName.rgAltEntry);
2985 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2991 SetLastError(CRYPT_E_ASN1_BADTAG);
2997 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
2998 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2999 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3001 struct AsnDecodeSequenceItem items[] = {
3002 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3003 DistPointName), CRYPT_AsnDecodeDistPointName,
3004 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3005 DistPointName.u.FullName.rgAltEntry), 0 },
3006 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3007 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3008 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3009 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3010 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3011 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3015 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3016 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3017 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3021 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3022 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3023 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3027 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3028 pDecodePara, pvStructInfo, *pcbStructInfo);
3032 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3033 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3034 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3036 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3037 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3041 SetLastError(STATUS_ACCESS_VIOLATION);
3048 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3049 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3050 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3054 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3055 pDecodePara, pvStructInfo, *pcbStructInfo);
3059 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3060 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3062 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3063 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3067 SetLastError(STATUS_ACCESS_VIOLATION);
3074 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3075 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3076 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3080 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3081 pDecodePara, pvStructInfo, *pcbStructInfo);
3085 struct AsnDecodeSequenceItem items[] = {
3086 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3087 DistPointName), CRYPT_AsnDecodeDistPointName,
3088 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3089 offsetof(CRL_ISSUING_DIST_POINT,
3090 DistPointName.u.FullName.rgAltEntry), 0 },
3091 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3092 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3094 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3095 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3097 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3098 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3099 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3100 OnlySomeReasonFlags.pbData), 0 },
3101 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3102 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3105 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3106 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3107 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3111 SetLastError(STATUS_ACCESS_VIOLATION);
3118 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3119 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3120 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3122 static HCRYPTOIDFUNCSET set = NULL;
3124 CryptDecodeObjectExFunc decodeFunc = NULL;
3125 HCRYPTOIDFUNCADDR hFunc = NULL;
3127 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
3128 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
3129 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3131 if (!pvStructInfo && !pcbStructInfo)
3133 SetLastError(ERROR_INVALID_PARAMETER);
3136 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3137 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3139 SetLastError(ERROR_FILE_NOT_FOUND);
3144 SetLastError(CRYPT_E_ASN1_EOD);
3147 if (cbEncoded > MAX_ENCODED_LEN)
3149 SetLastError(CRYPT_E_ASN1_LARGE);
3153 SetLastError(NOERROR);
3154 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3155 *(BYTE **)pvStructInfo = NULL;
3156 if (!HIWORD(lpszStructType))
3158 switch (LOWORD(lpszStructType))
3160 case (WORD)X509_CERT:
3161 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3163 case (WORD)X509_CERT_TO_BE_SIGNED:
3164 decodeFunc = CRYPT_AsnDecodeCert;
3166 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3167 decodeFunc = CRYPT_AsnDecodeCRL;
3169 case (WORD)X509_EXTENSIONS:
3170 decodeFunc = CRYPT_AsnDecodeExtensions;
3172 case (WORD)X509_NAME_VALUE:
3173 decodeFunc = CRYPT_AsnDecodeNameValue;
3175 case (WORD)X509_NAME:
3176 decodeFunc = CRYPT_AsnDecodeName;
3178 case (WORD)X509_PUBLIC_KEY_INFO:
3179 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
3181 case (WORD)X509_ALTERNATE_NAME:
3182 decodeFunc = CRYPT_AsnDecodeAltName;
3184 case (WORD)X509_BASIC_CONSTRAINTS:
3185 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3187 case (WORD)X509_BASIC_CONSTRAINTS2:
3188 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3190 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3191 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3193 case (WORD)X509_OCTET_STRING:
3194 decodeFunc = CRYPT_AsnDecodeOctets;
3196 case (WORD)X509_BITS:
3197 case (WORD)X509_KEY_USAGE:
3198 decodeFunc = CRYPT_AsnDecodeBits;
3200 case (WORD)X509_INTEGER:
3201 decodeFunc = CRYPT_AsnDecodeInt;
3203 case (WORD)X509_MULTI_BYTE_INTEGER:
3204 decodeFunc = CRYPT_AsnDecodeInteger;
3206 case (WORD)X509_MULTI_BYTE_UINT:
3207 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3209 case (WORD)X509_ENUMERATED:
3210 decodeFunc = CRYPT_AsnDecodeEnumerated;
3212 case (WORD)X509_CHOICE_OF_TIME:
3213 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3215 case (WORD)X509_SEQUENCE_OF_ANY:
3216 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3218 case (WORD)PKCS_UTC_TIME:
3219 decodeFunc = CRYPT_AsnDecodeUtcTime;
3221 case (WORD)X509_CRL_DIST_POINTS:
3222 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3224 case (WORD)X509_ENHANCED_KEY_USAGE:
3225 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3227 case (WORD)X509_ISSUING_DIST_POINT:
3228 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3231 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3234 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3235 decodeFunc = CRYPT_AsnDecodeExtensions;
3236 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3237 decodeFunc = CRYPT_AsnDecodeUtcTime;
3238 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3239 decodeFunc = CRYPT_AsnDecodeEnumerated;
3240 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3241 decodeFunc = CRYPT_AsnDecodeBits;
3242 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3243 decodeFunc = CRYPT_AsnDecodeOctets;
3244 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3245 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3246 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3247 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3248 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3249 decodeFunc = CRYPT_AsnDecodeAltName;
3250 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3251 decodeFunc = CRYPT_AsnDecodeAltName;
3252 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3253 decodeFunc = CRYPT_AsnDecodeAltName;
3254 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3255 decodeFunc = CRYPT_AsnDecodeAltName;
3256 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3257 decodeFunc = CRYPT_AsnDecodeAltName;
3258 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3259 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3260 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3261 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3262 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3263 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3265 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3266 debugstr_a(lpszStructType));
3270 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
3271 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3272 (void **)&decodeFunc, &hFunc);
3275 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3276 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3278 SetLastError(ERROR_FILE_NOT_FOUND);
3280 CryptFreeOIDFunctionAddress(hFunc, 0);