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));
564 memcpy(itemSizes, &itemSize, sizeof(itemSize));
568 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
570 itemSizes[cItems - 1].size = size;
572 ret = CRYPT_GetLen(ptr,
573 cbEncoded - (ptr - pbEncoded), &nextLen);
575 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
585 *pcbStructInfo = bytesNeeded;
586 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
587 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
592 struct GenericArray *array;
594 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
595 pvStructInfo = *(BYTE **)pvStructInfo;
596 array = (struct GenericArray *)pvStructInfo;
597 array->cItems = cItems;
599 array->rgItems = startingPointer;
601 array->rgItems = (BYTE *)array +
602 sizeof(struct GenericArray);
603 nextData = (BYTE *)array->rgItems +
604 array->cItems * arrayDesc->itemSize;
605 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
606 i < cItems && ptr - pbEncoded - 1 - lenBytes <
609 if (arrayDesc->hasPointer)
610 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
611 + arrayDesc->pointerOffset) = nextData;
612 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
613 itemSizes[i].encodedLen,
614 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
615 array->rgItems + i * arrayDesc->itemSize,
621 nextData += itemSizes[i].size - arrayDesc->itemSize;
622 ret = CRYPT_GetLen(ptr,
623 cbEncoded - (ptr - pbEncoded), &nextLen);
625 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
630 if (itemSizes != &itemSize)
631 CryptMemFree(itemSizes);
636 SetLastError(CRYPT_E_ASN1_BADTAG);
642 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
643 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
644 * to CRYPT_E_ASN1_CORRUPT.
645 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
648 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
649 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
650 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
655 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
657 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
658 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
660 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
661 bytesNeeded += 1 + lenBytes + dataLen;
664 *pcbStructInfo = bytesNeeded;
665 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
666 pvStructInfo, pcbStructInfo, bytesNeeded)))
668 CRYPT_DER_BLOB *blob;
670 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
671 pvStructInfo = *(BYTE **)pvStructInfo;
672 blob = (CRYPT_DER_BLOB *)pvStructInfo;
673 blob->cbData = 1 + lenBytes + dataLen;
676 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
677 blob->pbData = (BYTE *)pbEncoded;
680 assert(blob->pbData);
681 memcpy(blob->pbData, pbEncoded, blob->cbData);
686 SetLastError(CRYPT_E_ASN1_CORRUPT);
694 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
695 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
696 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
697 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
701 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
702 pDecodePara, pvStructInfo, *pcbStructInfo);
704 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
707 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
708 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
709 pvStructInfo, pcbStructInfo);
710 if (ret && pvStructInfo)
712 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
719 for (i = 0; i < blob->cbData / 2; i++)
721 temp = blob->pbData[i];
722 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
723 blob->pbData[blob->cbData - i - 1] = temp;
727 TRACE("returning %d (%08lx)\n", ret, GetLastError());
731 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
732 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
733 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
737 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
738 pDecodePara, pvStructInfo, *pcbStructInfo);
742 struct AsnDecodeSequenceItem items[] = {
743 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
744 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
745 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
746 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
747 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
748 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
749 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
750 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
751 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
752 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
755 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
756 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
757 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
758 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
759 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
763 SetLastError(STATUS_ACCESS_VIOLATION);
768 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
772 /* Internal function */
773 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
774 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
775 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
780 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
782 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
784 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
785 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
786 pvStructInfo, pcbStructInfo);
791 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
792 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
793 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
797 struct AsnDecodeSequenceItem items[] = {
798 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
799 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
800 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
801 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
804 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
805 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
806 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
810 /* Internal function */
811 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
812 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
813 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
818 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
820 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
822 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
823 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
824 pDecodePara, pvStructInfo, pcbStructInfo);
829 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
830 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
831 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
834 struct AsnDecodeSequenceItem items[] = {
835 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
836 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
837 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
838 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
839 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
840 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
841 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
842 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
843 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
844 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
846 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
847 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
849 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
850 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
852 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
853 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
854 FALSE, TRUE, offsetof(CERT_INFO,
855 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
856 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
857 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
858 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
859 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
860 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
861 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
862 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
863 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
864 offsetof(CERT_INFO, rgExtension), 0 },
867 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
868 pDecodePara, pvStructInfo, *pcbStructInfo);
870 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
871 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
872 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
874 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
878 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
879 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
880 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
884 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
885 pDecodePara, pvStructInfo, *pcbStructInfo);
889 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
892 /* First try to decode it as a signed cert. */
893 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
894 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
895 (BYTE *)&signedCert, &size);
899 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
900 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
901 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
903 LocalFree(signedCert);
905 /* Failing that, try it as an unsigned cert */
909 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
910 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
911 pDecodePara, pvStructInfo, pcbStructInfo);
916 SetLastError(STATUS_ACCESS_VIOLATION);
921 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
925 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
926 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
927 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
930 struct AsnDecodeSequenceItem items[] = {
931 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
932 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
933 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
934 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
935 sizeof(FILETIME), FALSE, FALSE, 0 },
936 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
937 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
938 offsetof(CRL_ENTRY, rgExtension), 0 },
940 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
942 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
945 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
946 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
947 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
951 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
952 * been set prior to calling.
954 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
955 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
956 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
959 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
960 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
961 offsetof(CRL_ENTRY, SerialNumber.pbData) };
962 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
964 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
965 pDecodePara, pvStructInfo, *pcbStructInfo);
967 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
968 pDecodePara, pvStructInfo, pcbStructInfo,
969 entries ? entries->rgItems : NULL);
970 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
974 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
975 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
976 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
978 struct AsnDecodeSequenceItem items[] = {
979 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
980 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
981 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
982 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
983 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
984 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
985 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
987 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
988 sizeof(FILETIME), FALSE, FALSE, 0 },
989 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
990 sizeof(FILETIME), TRUE, FALSE, 0 },
991 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
992 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
993 offsetof(CRL_INFO, rgCRLEntry), 0 },
994 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
995 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
996 offsetof(CRL_INFO, rgExtension), 0 },
1000 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1001 pDecodePara, pvStructInfo, *pcbStructInfo);
1003 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1004 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1005 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1007 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1011 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1012 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1013 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1017 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1018 pDecodePara, pvStructInfo, *pcbStructInfo);
1022 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1025 /* First try to decode it as a signed crl. */
1026 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1027 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1028 (BYTE *)&signedCrl, &size);
1032 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1033 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1034 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1035 pvStructInfo, pcbStructInfo);
1036 LocalFree(signedCrl);
1038 /* Failing that, try it as an unsigned crl */
1042 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1043 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1044 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1049 SetLastError(STATUS_ACCESS_VIOLATION);
1054 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1058 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1059 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1060 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1064 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1065 pDecodePara, pvStructInfo, *pcbStructInfo);
1067 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1071 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1073 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1074 DWORD bytesNeeded = sizeof(LPSTR);
1078 /* The largest possible string for the first two components
1079 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1084 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1085 pbEncoded[1 + lenBytes] / 40,
1086 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1088 bytesNeeded += strlen(firstTwo) + 1;
1089 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1090 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1092 /* large enough for ".4000000" */
1096 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1103 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1106 SetLastError(CRYPT_E_ASN1_CORRUPT);
1113 snprintf(str, sizeof(str), ".%d", val);
1114 bytesNeeded += strlen(str);
1119 *pcbStructInfo = bytesNeeded;
1120 else if (*pcbStructInfo < bytesNeeded)
1122 *pcbStructInfo = bytesNeeded;
1123 SetLastError(ERROR_MORE_DATA);
1131 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1134 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1135 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1137 pszObjId += strlen(pszObjId);
1138 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1139 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1143 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1152 sprintf(pszObjId, ".%d", val);
1153 pszObjId += strlen(pszObjId);
1157 *(LPSTR *)pvStructInfo = NULL;
1158 *pcbStructInfo = bytesNeeded;
1165 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1168 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1169 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1170 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1172 struct AsnDecodeSequenceItem items[] = {
1173 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1174 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1175 offsetof(CERT_EXTENSION, pszObjId), 0 },
1176 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1177 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1178 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1179 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1180 offsetof(CERT_EXTENSION, Value.pbData) },
1183 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1185 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
1189 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1190 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1191 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1192 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1194 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1195 debugstr_a(ext->pszObjId));
1196 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1200 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1201 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1202 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1205 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1206 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1207 offsetof(CERT_EXTENSION, pszObjId) };
1208 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1210 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1211 pDecodePara, pvStructInfo, *pcbStructInfo);
1213 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1214 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1218 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1219 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1220 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1226 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1227 lpszStructType, pbEncoded, cbEncoded,
1228 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1229 if (ret && pvStructInfo)
1231 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1232 pcbStructInfo, *pcbStructInfo);
1235 CERT_EXTENSIONS *exts;
1237 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1238 pvStructInfo = *(BYTE **)pvStructInfo;
1239 exts = (CERT_EXTENSIONS *)pvStructInfo;
1240 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1241 sizeof(CERT_EXTENSIONS));
1242 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1243 lpszStructType, pbEncoded, cbEncoded,
1244 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1251 SetLastError(STATUS_ACCESS_VIOLATION);
1258 /* Warning: this assumes the address of value->Value.pbData is already set, in
1259 * order to avoid overwriting memory. (In some cases, it may change it, if it
1260 * doesn't copy anything to memory.) Be sure to set it correctly!
1262 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1263 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1264 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1268 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1270 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1272 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1274 switch (pbEncoded[0])
1276 case ASN_NUMERICSTRING:
1277 case ASN_PRINTABLESTRING:
1282 FIXME("Unimplemented string type %02x\n", pbEncoded[0]);
1283 SetLastError(OSS_UNIMPLEMENTED);
1288 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE);
1290 switch (pbEncoded[0])
1292 case ASN_NUMERICSTRING:
1293 case ASN_PRINTABLESTRING:
1296 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1297 bytesNeeded += dataLen;
1301 *pcbStructInfo = bytesNeeded;
1302 else if (*pcbStructInfo < bytesNeeded)
1304 *pcbStructInfo = bytesNeeded;
1305 SetLastError(ERROR_MORE_DATA);
1310 *pcbStructInfo = bytesNeeded;
1311 switch (pbEncoded[0])
1313 case ASN_NUMERICSTRING:
1314 value->dwValueType = CERT_RDN_NUMERIC_STRING;
1316 case ASN_PRINTABLESTRING:
1317 value->dwValueType = CERT_RDN_PRINTABLE_STRING;
1320 value->dwValueType = CERT_RDN_IA5_STRING;
1323 value->dwValueType = CERT_RDN_T61_STRING;
1328 switch (pbEncoded[0])
1330 case ASN_NUMERICSTRING:
1331 case ASN_PRINTABLESTRING:
1334 value->Value.cbData = dataLen;
1335 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1336 value->Value.pbData = (BYTE *)pbEncoded + 1 +
1340 assert(value->Value.pbData);
1341 memcpy(value->Value.pbData,
1342 pbEncoded + 1 + lenBytes, dataLen);
1349 value->Value.cbData = 0;
1350 value->Value.pbData = NULL;
1358 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1359 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1360 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1366 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1367 lpszStructType, pbEncoded, cbEncoded,
1368 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1369 if (ret && pvStructInfo)
1371 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1372 pcbStructInfo, *pcbStructInfo);
1375 CERT_NAME_VALUE *value;
1377 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1378 pvStructInfo = *(BYTE **)pvStructInfo;
1379 value = (CERT_NAME_VALUE *)pvStructInfo;
1380 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1381 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1382 lpszStructType, pbEncoded, cbEncoded,
1383 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1390 SetLastError(STATUS_ACCESS_VIOLATION);
1397 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1398 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1399 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1402 struct AsnDecodeSequenceItem items[] = {
1403 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1404 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1405 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1406 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1407 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1408 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1410 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1412 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1413 pvStructInfo, *pcbStructInfo);
1416 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1417 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1418 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1419 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1422 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1423 debugstr_a(attr->pszObjId));
1424 TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1426 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1430 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1431 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1432 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1435 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1436 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1437 offsetof(CERT_RDN_ATTR, pszObjId) };
1438 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1440 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1441 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1445 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1446 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1447 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1453 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1454 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1455 offsetof(CERT_RDN, rgRDNAttr) };
1457 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1458 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1462 SetLastError(STATUS_ACCESS_VIOLATION);
1469 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1470 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1471 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1474 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1476 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1477 pDecodePara, pvStructInfo, *pcbStructInfo);
1479 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1480 bytesNeeded += cbEncoded;
1482 *pcbStructInfo = bytesNeeded;
1483 else if (*pcbStructInfo < bytesNeeded)
1485 SetLastError(ERROR_MORE_DATA);
1486 *pcbStructInfo = bytesNeeded;
1491 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1493 *pcbStructInfo = bytesNeeded;
1494 blob->cbData = cbEncoded;
1495 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1496 blob->pbData = (LPBYTE)pbEncoded;
1499 assert(blob->pbData);
1500 memcpy(blob->pbData, pbEncoded, blob->cbData);
1506 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1507 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1508 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1510 CRYPT_ALGORITHM_IDENTIFIER *algo =
1511 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1513 struct AsnDecodeSequenceItem items[] = {
1514 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1515 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1516 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1517 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1518 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1519 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1522 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1523 pDecodePara, pvStructInfo, *pcbStructInfo);
1525 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1526 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1527 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1528 if (ret && pvStructInfo)
1530 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1531 debugstr_a(algo->pszObjId));
1536 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1537 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1538 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1541 struct AsnDecodeSequenceItem items[] = {
1542 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1543 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1544 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1545 Algorithm.pszObjId) },
1546 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1547 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1548 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1550 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1552 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1553 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1554 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1555 info->Algorithm.Parameters.pbData : NULL);
1559 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1560 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1561 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1569 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1570 lpszStructType, pbEncoded, cbEncoded,
1571 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1574 *pcbStructInfo = bytesNeeded;
1575 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1576 pvStructInfo, pcbStructInfo, bytesNeeded)))
1578 PCERT_PUBLIC_KEY_INFO info;
1580 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1581 pvStructInfo = *(BYTE **)pvStructInfo;
1582 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1583 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
1584 sizeof(CERT_PUBLIC_KEY_INFO);
1585 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1586 lpszStructType, pbEncoded, cbEncoded,
1587 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1594 SetLastError(STATUS_ACCESS_VIOLATION);
1601 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
1602 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1603 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1609 SetLastError(CRYPT_E_ASN1_CORRUPT);
1612 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
1614 SetLastError(CRYPT_E_ASN1_CORRUPT);
1617 if (pbEncoded[1] > 1)
1619 SetLastError(CRYPT_E_ASN1_CORRUPT);
1624 *pcbStructInfo = sizeof(BOOL);
1627 else if (*pcbStructInfo < sizeof(BOOL))
1629 *pcbStructInfo = sizeof(BOOL);
1630 SetLastError(ERROR_MORE_DATA);
1635 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
1638 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1642 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
1643 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1644 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1646 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
1647 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
1650 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1651 pDecodePara, pvStructInfo, *pcbStructInfo);
1655 SetLastError(CRYPT_E_ASN1_CORRUPT);
1658 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
1660 SetLastError(CRYPT_E_ASN1_BADTAG);
1663 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1664 if (1 + lenBytes > cbEncoded)
1666 SetLastError(CRYPT_E_ASN1_CORRUPT);
1669 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1671 switch (pbEncoded[0] & ASN_TYPE_MASK)
1673 case 1: /* rfc822Name */
1674 case 2: /* dNSName */
1675 case 6: /* uniformResourceIdentifier */
1676 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1678 case 7: /* iPAddress */
1679 bytesNeeded += dataLen;
1681 case 8: /* registeredID */
1682 /* FIXME: decode as OID */
1683 case 0: /* otherName */
1684 case 4: /* directoryName */
1686 SetLastError(CRYPT_E_ASN1_BADTAG);
1689 case 3: /* x400Address, unimplemented */
1690 case 5: /* ediPartyName, unimplemented */
1691 SetLastError(CRYPT_E_ASN1_BADTAG);
1695 SetLastError(CRYPT_E_ASN1_CORRUPT);
1701 *pcbStructInfo = bytesNeeded;
1702 else if (*pcbStructInfo < bytesNeeded)
1704 *pcbStructInfo = bytesNeeded;
1705 SetLastError(ERROR_MORE_DATA);
1710 *pcbStructInfo = bytesNeeded;
1711 /* MS used values one greater than the asn1 ones.. sigh */
1712 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
1713 switch (pbEncoded[0] & ASN_TYPE_MASK)
1715 case 1: /* rfc822Name */
1716 case 2: /* dNSName */
1717 case 6: /* uniformResourceIdentifier */
1721 for (i = 0; i < dataLen; i++)
1722 entry->u.pwszURL[i] =
1723 (WCHAR)pbEncoded[1 + lenBytes + i];
1724 entry->u.pwszURL[i] = 0;
1725 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
1726 debugstr_w(entry->u.pwszURL));
1729 case 7: /* iPAddress */
1730 /* The next data pointer is in the pwszURL spot, that is,
1731 * the first 4 bytes. Need to move it to the next spot.
1733 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
1734 entry->u.IPAddress.cbData = dataLen;
1735 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
1745 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
1746 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1747 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1750 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1751 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
1752 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
1753 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
1755 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1756 pDecodePara, pvStructInfo, *pcbStructInfo);
1759 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
1760 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1761 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
1765 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
1766 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1767 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1771 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1772 pDecodePara, pvStructInfo, *pcbStructInfo);
1776 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1777 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
1778 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
1780 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1781 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1785 SetLastError(STATUS_ACCESS_VIOLATION);
1792 struct PATH_LEN_CONSTRAINT
1794 BOOL fPathLenConstraint;
1795 DWORD dwPathLenConstraint;
1798 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
1799 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1800 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1804 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1805 pvStructInfo, *pcbStructInfo);
1809 if (pbEncoded[0] == ASN_INTEGER)
1811 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
1814 *pcbStructInfo = bytesNeeded;
1815 else if (*pcbStructInfo < bytesNeeded)
1817 SetLastError(ERROR_MORE_DATA);
1818 *pcbStructInfo = bytesNeeded;
1823 struct PATH_LEN_CONSTRAINT *constraint =
1824 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
1825 DWORD size = sizeof(constraint->dwPathLenConstraint);
1827 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
1828 pbEncoded, cbEncoded, 0, NULL,
1829 &constraint->dwPathLenConstraint, &size);
1831 constraint->fPathLenConstraint = TRUE;
1832 TRACE("got an int, dwPathLenConstraint is %ld\n",
1833 constraint->dwPathLenConstraint);
1838 SetLastError(CRYPT_E_ASN1_CORRUPT);
1842 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1846 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
1847 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1848 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1851 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1852 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
1853 offsetof(CERT_NAME_BLOB, pbData) };
1854 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1856 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1857 pDecodePara, pvStructInfo, *pcbStructInfo);
1859 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1860 pDecodePara, pvStructInfo, pcbStructInfo,
1861 entries ? entries->rgItems : NULL);
1862 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1866 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
1867 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1868 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1874 struct AsnDecodeSequenceItem items[] = {
1875 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
1876 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1877 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
1878 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
1879 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
1880 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
1881 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
1882 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
1883 sizeof(struct GenericArray), TRUE, TRUE,
1884 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
1887 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1888 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1889 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1893 SetLastError(STATUS_ACCESS_VIOLATION);
1900 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
1901 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1902 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1908 struct AsnDecodeSequenceItem items[] = {
1909 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
1910 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
1911 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
1912 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
1913 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
1916 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1917 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1918 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1922 SetLastError(STATUS_ACCESS_VIOLATION);
1929 #define RSA1_MAGIC 0x31415352
1931 struct DECODED_RSA_PUB_KEY
1934 CRYPT_INTEGER_BLOB modulus;
1937 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
1938 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1939 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1945 struct AsnDecodeSequenceItem items[] = {
1946 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
1947 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
1948 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
1950 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
1951 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
1953 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
1956 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1957 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
1958 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
1961 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1962 decodedKey->modulus.cbData;
1966 *pcbStructInfo = bytesNeeded;
1969 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1970 pvStructInfo, pcbStructInfo, bytesNeeded)))
1973 RSAPUBKEY *rsaPubKey;
1975 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1976 pvStructInfo = *(BYTE **)pvStructInfo;
1977 hdr = (BLOBHEADER *)pvStructInfo;
1978 hdr->bType = PUBLICKEYBLOB;
1979 hdr->bVersion = CUR_BLOB_VERSION;
1981 hdr->aiKeyAlg = CALG_RSA_KEYX;
1982 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
1983 sizeof(BLOBHEADER));
1984 rsaPubKey->magic = RSA1_MAGIC;
1985 rsaPubKey->pubexp = decodedKey->pubexp;
1986 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
1987 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
1988 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
1989 decodedKey->modulus.cbData);
1991 LocalFree(decodedKey);
1996 SetLastError(STATUS_ACCESS_VIOLATION);
2003 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2004 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2005 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2008 DWORD bytesNeeded, dataLen;
2010 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2011 pDecodePara, pvStructInfo, *pcbStructInfo);
2013 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2015 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2016 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2018 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2020 *pcbStructInfo = bytesNeeded;
2021 else if (*pcbStructInfo < bytesNeeded)
2023 SetLastError(ERROR_MORE_DATA);
2024 *pcbStructInfo = bytesNeeded;
2029 CRYPT_DATA_BLOB *blob;
2030 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2032 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2033 blob->cbData = dataLen;
2034 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2035 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2038 assert(blob->pbData);
2040 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2048 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2049 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2050 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2054 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2055 pDecodePara, pvStructInfo, *pcbStructInfo);
2063 SetLastError(CRYPT_E_ASN1_CORRUPT);
2066 else if (pbEncoded[0] != ASN_OCTETSTRING)
2068 SetLastError(CRYPT_E_ASN1_BADTAG);
2071 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2072 lpszStructType, pbEncoded, cbEncoded,
2073 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2076 *pcbStructInfo = bytesNeeded;
2077 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2078 pvStructInfo, pcbStructInfo, bytesNeeded)))
2080 CRYPT_DATA_BLOB *blob;
2082 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2083 pvStructInfo = *(BYTE **)pvStructInfo;
2084 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2085 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2086 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2087 lpszStructType, pbEncoded, cbEncoded,
2088 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2095 SetLastError(STATUS_ACCESS_VIOLATION);
2102 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2103 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2104 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2108 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2109 pDecodePara, pvStructInfo, *pcbStructInfo);
2111 if (pbEncoded[0] == ASN_BITSTRING)
2113 DWORD bytesNeeded, dataLen;
2115 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2117 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2118 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2120 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2122 *pcbStructInfo = bytesNeeded;
2123 else if (*pcbStructInfo < bytesNeeded)
2125 *pcbStructInfo = bytesNeeded;
2126 SetLastError(ERROR_MORE_DATA);
2131 CRYPT_BIT_BLOB *blob;
2133 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2134 blob->cbData = dataLen - 1;
2135 blob->cUnusedBits = *(pbEncoded + 1 +
2136 GET_LEN_BYTES(pbEncoded[1]));
2137 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2139 blob->pbData = (BYTE *)pbEncoded + 2 +
2140 GET_LEN_BYTES(pbEncoded[1]);
2144 assert(blob->pbData);
2147 BYTE mask = 0xff << blob->cUnusedBits;
2149 memcpy(blob->pbData, pbEncoded + 2 +
2150 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2151 blob->pbData[blob->cbData - 1] &= mask;
2159 SetLastError(CRYPT_E_ASN1_BADTAG);
2162 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2166 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2167 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2168 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2172 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2173 pDecodePara, pvStructInfo, pcbStructInfo);
2179 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2180 lpszStructType, pbEncoded, cbEncoded,
2181 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2184 *pcbStructInfo = bytesNeeded;
2185 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2186 pvStructInfo, pcbStructInfo, bytesNeeded)))
2188 CRYPT_BIT_BLOB *blob;
2190 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2191 pvStructInfo = *(BYTE **)pvStructInfo;
2192 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2193 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2194 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2195 lpszStructType, pbEncoded, cbEncoded,
2196 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2203 SetLastError(STATUS_ACCESS_VIOLATION);
2207 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2211 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2212 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2213 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2219 *pcbStructInfo = sizeof(int);
2224 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2225 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2226 DWORD size = sizeof(buf);
2228 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2229 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2230 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size);
2233 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2234 pvStructInfo, pcbStructInfo, sizeof(int))))
2238 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2239 pvStructInfo = *(BYTE **)pvStructInfo;
2240 if (blob->pbData[blob->cbData - 1] & 0x80)
2242 /* initialize to a negative value to sign-extend */
2247 for (i = 0; i < blob->cbData; i++)
2250 val |= blob->pbData[blob->cbData - i - 1];
2252 memcpy(pvStructInfo, &val, sizeof(int));
2255 else if (GetLastError() == ERROR_MORE_DATA)
2256 SetLastError(CRYPT_E_ASN1_LARGE);
2260 SetLastError(STATUS_ACCESS_VIOLATION);
2267 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2268 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2269 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2273 if (pbEncoded[0] == ASN_INTEGER)
2275 DWORD bytesNeeded, dataLen;
2277 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2279 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2281 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2283 *pcbStructInfo = bytesNeeded;
2284 else if (*pcbStructInfo < bytesNeeded)
2286 *pcbStructInfo = bytesNeeded;
2287 SetLastError(ERROR_MORE_DATA);
2292 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2294 blob->cbData = dataLen;
2295 assert(blob->pbData);
2300 for (i = 0; i < blob->cbData; i++)
2302 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2311 SetLastError(CRYPT_E_ASN1_BADTAG);
2317 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2318 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2319 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2327 if ((ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2328 lpszStructType, pbEncoded, cbEncoded,
2329 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2332 *pcbStructInfo = bytesNeeded;
2333 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2334 pvStructInfo, pcbStructInfo, bytesNeeded)))
2336 CRYPT_INTEGER_BLOB *blob;
2338 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2339 pvStructInfo = *(BYTE **)pvStructInfo;
2340 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2341 blob->pbData = (BYTE *)pvStructInfo +
2342 sizeof(CRYPT_INTEGER_BLOB);
2343 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2344 lpszStructType, pbEncoded, cbEncoded,
2345 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2352 SetLastError(STATUS_ACCESS_VIOLATION);
2359 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
2360 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2361 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2362 void *pvStructInfo, DWORD *pcbStructInfo)
2366 if (pbEncoded[0] == ASN_INTEGER)
2368 DWORD bytesNeeded, dataLen;
2370 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2372 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2374 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2376 *pcbStructInfo = bytesNeeded;
2377 else if (*pcbStructInfo < bytesNeeded)
2379 *pcbStructInfo = bytesNeeded;
2380 SetLastError(ERROR_MORE_DATA);
2385 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2387 blob->cbData = dataLen;
2388 assert(blob->pbData);
2389 /* remove leading zero byte if it exists */
2390 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2399 for (i = 0; i < blob->cbData; i++)
2401 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2410 SetLastError(CRYPT_E_ASN1_BADTAG);
2416 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2417 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2418 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2426 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2427 lpszStructType, pbEncoded, cbEncoded,
2428 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2431 *pcbStructInfo = bytesNeeded;
2432 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2433 pvStructInfo, pcbStructInfo, bytesNeeded)))
2435 CRYPT_INTEGER_BLOB *blob;
2437 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2438 pvStructInfo = *(BYTE **)pvStructInfo;
2439 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2440 blob->pbData = (BYTE *)pvStructInfo +
2441 sizeof(CRYPT_INTEGER_BLOB);
2442 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2443 lpszStructType, pbEncoded, cbEncoded,
2444 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2451 SetLastError(STATUS_ACCESS_VIOLATION);
2458 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
2459 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2460 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2466 *pcbStructInfo = sizeof(int);
2471 if (pbEncoded[0] == ASN_ENUMERATED)
2473 unsigned int val = 0, i;
2477 SetLastError(CRYPT_E_ASN1_EOD);
2480 else if (pbEncoded[1] == 0)
2482 SetLastError(CRYPT_E_ASN1_CORRUPT);
2487 /* A little strange looking, but we have to accept a sign byte:
2488 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
2489 * assuming a small length is okay here, it has to be in short
2492 if (pbEncoded[1] > sizeof(unsigned int) + 1)
2494 SetLastError(CRYPT_E_ASN1_LARGE);
2497 for (i = 0; i < pbEncoded[1]; i++)
2500 val |= pbEncoded[2 + i];
2502 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2503 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
2505 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2506 pvStructInfo = *(BYTE **)pvStructInfo;
2507 memcpy(pvStructInfo, &val, sizeof(unsigned int));
2513 SetLastError(CRYPT_E_ASN1_BADTAG);
2519 SetLastError(STATUS_ACCESS_VIOLATION);
2526 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
2529 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
2534 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
2536 if (!isdigit(*(pbEncoded))) \
2538 SetLastError(CRYPT_E_ASN1_CORRUPT); \
2544 (word) += *(pbEncoded)++ - '0'; \
2549 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
2550 SYSTEMTIME *sysTime)
2557 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
2559 WORD hours, minutes = 0;
2560 BYTE sign = *pbEncoded++;
2563 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
2564 if (ret && hours >= 24)
2566 SetLastError(CRYPT_E_ASN1_CORRUPT);
2571 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
2572 if (ret && minutes >= 60)
2574 SetLastError(CRYPT_E_ASN1_CORRUPT);
2582 sysTime->wHour += hours;
2583 sysTime->wMinute += minutes;
2587 if (hours > sysTime->wHour)
2590 sysTime->wHour = 24 - (hours - sysTime->wHour);
2593 sysTime->wHour -= hours;
2594 if (minutes > sysTime->wMinute)
2597 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
2600 sysTime->wMinute -= minutes;
2607 SetLastError(STATUS_ACCESS_VIOLATION);
2614 #define MIN_ENCODED_TIME_LENGTH 10
2616 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
2617 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2618 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2624 *pcbStructInfo = sizeof(FILETIME);
2630 if (pbEncoded[0] == ASN_UTCTIME)
2634 SetLastError(CRYPT_E_ASN1_EOD);
2637 else if (pbEncoded[1] > 0x7f)
2639 /* long-form date strings really can't be valid */
2640 SetLastError(CRYPT_E_ASN1_CORRUPT);
2645 SYSTEMTIME sysTime = { 0 };
2646 BYTE len = pbEncoded[1];
2648 if (len < MIN_ENCODED_TIME_LENGTH)
2650 SetLastError(CRYPT_E_ASN1_CORRUPT);
2656 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
2657 if (sysTime.wYear >= 50)
2658 sysTime.wYear += 1900;
2660 sysTime.wYear += 2000;
2661 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2662 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2663 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2664 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
2667 if (len >= 2 && isdigit(*pbEncoded) &&
2668 isdigit(*(pbEncoded + 1)))
2669 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2671 else if (isdigit(*pbEncoded))
2672 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
2675 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2678 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2679 pDecodePara, pvStructInfo, pcbStructInfo,
2682 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2683 pvStructInfo = *(BYTE **)pvStructInfo;
2684 ret = SystemTimeToFileTime(&sysTime,
2685 (FILETIME *)pvStructInfo);
2692 SetLastError(CRYPT_E_ASN1_BADTAG);
2698 SetLastError(STATUS_ACCESS_VIOLATION);
2705 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
2706 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2707 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2713 *pcbStructInfo = sizeof(FILETIME);
2719 if (pbEncoded[0] == ASN_GENERALTIME)
2723 SetLastError(CRYPT_E_ASN1_EOD);
2726 else if (pbEncoded[1] > 0x7f)
2728 /* long-form date strings really can't be valid */
2729 SetLastError(CRYPT_E_ASN1_CORRUPT);
2734 BYTE len = pbEncoded[1];
2736 if (len < MIN_ENCODED_TIME_LENGTH)
2738 SetLastError(CRYPT_E_ASN1_CORRUPT);
2743 SYSTEMTIME sysTime = { 0 };
2746 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
2747 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2748 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2749 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2752 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2755 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2757 if (ret && len > 0 && (*pbEncoded == '.' ||
2764 /* workaround macro weirdness */
2765 digits = min(len, 3);
2766 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
2767 sysTime.wMilliseconds);
2770 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2773 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2774 pDecodePara, pvStructInfo, pcbStructInfo,
2777 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2778 pvStructInfo = *(BYTE **)pvStructInfo;
2779 ret = SystemTimeToFileTime(&sysTime,
2780 (FILETIME *)pvStructInfo);
2787 SetLastError(CRYPT_E_ASN1_BADTAG);
2793 SetLastError(STATUS_ACCESS_VIOLATION);
2800 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
2801 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2802 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2808 if (pbEncoded[0] == ASN_UTCTIME)
2809 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
2810 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2812 else if (pbEncoded[0] == ASN_GENERALTIME)
2813 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
2814 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
2815 pvStructInfo, pcbStructInfo);
2818 SetLastError(CRYPT_E_ASN1_BADTAG);
2824 SetLastError(STATUS_ACCESS_VIOLATION);
2831 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
2832 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2833 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2839 if (pbEncoded[0] == ASN_SEQUENCEOF)
2841 DWORD bytesNeeded, dataLen, remainingLen, cValue;
2843 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2848 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2849 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
2851 ptr = pbEncoded + 1 + lenBytes;
2852 remainingLen = dataLen;
2853 while (ret && remainingLen)
2857 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
2860 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
2862 remainingLen -= 1 + nextLenBytes + nextLen;
2863 ptr += 1 + nextLenBytes + nextLen;
2864 bytesNeeded += sizeof(CRYPT_DER_BLOB);
2865 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2866 bytesNeeded += 1 + nextLenBytes + nextLen;
2872 CRYPT_SEQUENCE_OF_ANY *seq;
2876 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2877 pvStructInfo, pcbStructInfo, bytesNeeded)))
2879 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2880 pvStructInfo = *(BYTE **)pvStructInfo;
2881 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2882 seq->cValue = cValue;
2883 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
2885 nextPtr = (BYTE *)seq->rgValue +
2886 cValue * sizeof(CRYPT_DER_BLOB);
2887 ptr = pbEncoded + 1 + lenBytes;
2888 remainingLen = dataLen;
2890 while (ret && remainingLen)
2894 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
2897 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
2899 seq->rgValue[i].cbData = 1 + nextLenBytes +
2901 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2902 seq->rgValue[i].pbData = (BYTE *)ptr;
2905 seq->rgValue[i].pbData = nextPtr;
2906 memcpy(nextPtr, ptr, 1 + nextLenBytes +
2908 nextPtr += 1 + nextLenBytes + nextLen;
2910 remainingLen -= 1 + nextLenBytes + nextLen;
2911 ptr += 1 + nextLenBytes + nextLen;
2921 SetLastError(CRYPT_E_ASN1_BADTAG);
2927 SetLastError(STATUS_ACCESS_VIOLATION);
2934 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
2935 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2936 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2940 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
2942 DWORD bytesNeeded, dataLen;
2944 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2946 struct AsnArrayDescriptor arrayDesc = {
2947 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
2948 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2949 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2950 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2956 ret = CRYPT_AsnDecodeArray(&arrayDesc,
2957 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
2958 0, NULL, NULL, &nameLen, NULL);
2959 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
2962 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
2964 *pcbStructInfo = bytesNeeded;
2965 else if (*pcbStructInfo < bytesNeeded)
2967 *pcbStructInfo = bytesNeeded;
2968 SetLastError(ERROR_MORE_DATA);
2973 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
2977 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2978 ret = CRYPT_AsnDecodeArray(&arrayDesc,
2979 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
2980 0, NULL, &name->u.FullName, pcbStructInfo,
2981 name->u.FullName.rgAltEntry);
2984 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2990 SetLastError(CRYPT_E_ASN1_BADTAG);
2996 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
2997 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2998 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3000 struct AsnDecodeSequenceItem items[] = {
3001 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3002 DistPointName), CRYPT_AsnDecodeDistPointName,
3003 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3004 DistPointName.u.FullName.rgAltEntry), 0 },
3005 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3006 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3007 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3008 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3009 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3010 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3014 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3015 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3016 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3020 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3021 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3022 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3026 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3027 pDecodePara, pvStructInfo, *pcbStructInfo);
3031 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3032 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3033 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3035 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3036 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3040 SetLastError(STATUS_ACCESS_VIOLATION);
3047 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3048 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3049 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3053 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3054 pDecodePara, pvStructInfo, *pcbStructInfo);
3058 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3059 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3061 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3062 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3066 SetLastError(STATUS_ACCESS_VIOLATION);
3073 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3074 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3075 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3079 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3080 pDecodePara, pvStructInfo, *pcbStructInfo);
3084 struct AsnDecodeSequenceItem items[] = {
3085 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3086 DistPointName), CRYPT_AsnDecodeDistPointName,
3087 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3088 offsetof(CRL_ISSUING_DIST_POINT,
3089 DistPointName.u.FullName.rgAltEntry), 0 },
3090 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3091 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3093 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3094 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3096 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3097 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3098 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3099 OnlySomeReasonFlags.pbData), 0 },
3100 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3101 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3104 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3105 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3106 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3110 SetLastError(STATUS_ACCESS_VIOLATION);
3117 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3118 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3119 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3121 static HCRYPTOIDFUNCSET set = NULL;
3123 CryptDecodeObjectExFunc decodeFunc = NULL;
3124 HCRYPTOIDFUNCADDR hFunc = NULL;
3126 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
3127 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
3128 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3130 if (!pvStructInfo && !pcbStructInfo)
3132 SetLastError(ERROR_INVALID_PARAMETER);
3135 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3136 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3138 SetLastError(ERROR_FILE_NOT_FOUND);
3143 SetLastError(CRYPT_E_ASN1_EOD);
3146 if (cbEncoded > MAX_ENCODED_LEN)
3148 SetLastError(CRYPT_E_ASN1_LARGE);
3152 SetLastError(NOERROR);
3153 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3154 *(BYTE **)pvStructInfo = NULL;
3155 if (!HIWORD(lpszStructType))
3157 switch (LOWORD(lpszStructType))
3159 case (WORD)X509_CERT:
3160 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3162 case (WORD)X509_CERT_TO_BE_SIGNED:
3163 decodeFunc = CRYPT_AsnDecodeCert;
3165 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3166 decodeFunc = CRYPT_AsnDecodeCRL;
3168 case (WORD)X509_EXTENSIONS:
3169 decodeFunc = CRYPT_AsnDecodeExtensions;
3171 case (WORD)X509_NAME_VALUE:
3172 decodeFunc = CRYPT_AsnDecodeNameValue;
3174 case (WORD)X509_NAME:
3175 decodeFunc = CRYPT_AsnDecodeName;
3177 case (WORD)X509_PUBLIC_KEY_INFO:
3178 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
3180 case (WORD)X509_ALTERNATE_NAME:
3181 decodeFunc = CRYPT_AsnDecodeAltName;
3183 case (WORD)X509_BASIC_CONSTRAINTS:
3184 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3186 case (WORD)X509_BASIC_CONSTRAINTS2:
3187 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3189 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3190 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3192 case (WORD)X509_OCTET_STRING:
3193 decodeFunc = CRYPT_AsnDecodeOctets;
3195 case (WORD)X509_BITS:
3196 case (WORD)X509_KEY_USAGE:
3197 decodeFunc = CRYPT_AsnDecodeBits;
3199 case (WORD)X509_INTEGER:
3200 decodeFunc = CRYPT_AsnDecodeInt;
3202 case (WORD)X509_MULTI_BYTE_INTEGER:
3203 decodeFunc = CRYPT_AsnDecodeInteger;
3205 case (WORD)X509_MULTI_BYTE_UINT:
3206 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3208 case (WORD)X509_ENUMERATED:
3209 decodeFunc = CRYPT_AsnDecodeEnumerated;
3211 case (WORD)X509_CHOICE_OF_TIME:
3212 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3214 case (WORD)X509_SEQUENCE_OF_ANY:
3215 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3217 case (WORD)PKCS_UTC_TIME:
3218 decodeFunc = CRYPT_AsnDecodeUtcTime;
3220 case (WORD)X509_CRL_DIST_POINTS:
3221 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3223 case (WORD)X509_ENHANCED_KEY_USAGE:
3224 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3226 case (WORD)X509_ISSUING_DIST_POINT:
3227 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3230 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3233 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3234 decodeFunc = CRYPT_AsnDecodeExtensions;
3235 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3236 decodeFunc = CRYPT_AsnDecodeUtcTime;
3237 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3238 decodeFunc = CRYPT_AsnDecodeEnumerated;
3239 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3240 decodeFunc = CRYPT_AsnDecodeBits;
3241 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3242 decodeFunc = CRYPT_AsnDecodeOctets;
3243 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3244 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3245 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3246 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3247 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3248 decodeFunc = CRYPT_AsnDecodeAltName;
3249 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3250 decodeFunc = CRYPT_AsnDecodeAltName;
3251 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3252 decodeFunc = CRYPT_AsnDecodeAltName;
3253 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3254 decodeFunc = CRYPT_AsnDecodeAltName;
3255 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3256 decodeFunc = CRYPT_AsnDecodeAltName;
3257 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3258 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3259 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3260 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3261 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3262 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3264 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3265 debugstr_a(lpszStructType));
3269 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
3270 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3271 (void **)&decodeFunc, &hFunc);
3274 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3275 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3277 SetLastError(ERROR_FILE_NOT_FOUND);
3279 CryptFreeOIDFunctionAddress(hFunc, 0);