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
46 #include "wine/debug.h"
47 #include "wine/exception.h"
48 #include "crypt32_private.h"
50 /* This is a bit arbitrary, but to set some limit: */
51 #define MAX_ENCODED_LEN 0x02000000
53 #define ASN_FLAGS_MASK 0xe0
54 #define ASN_TYPE_MASK 0x1f
56 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
64 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
65 DWORD, DWORD, void *, DWORD *);
66 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
67 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
69 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
70 * The dwCertEncodingType and lpszStructType are ignored by the built-in
71 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
72 * since it must call functions in external DLLs that follow these signatures.
74 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
75 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
76 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
77 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
78 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
79 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
80 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
81 * time, doesn't do memory allocation, and doesn't do exception handling.
82 * (This isn't intended to be the externally-called one.)
84 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
86 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
87 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
88 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
89 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
90 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
91 /* Internal function */
92 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
93 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
94 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
97 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
98 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
99 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
100 * member has been initialized, doesn't do exception handling, and doesn't do
103 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
104 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
105 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
106 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
107 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
108 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
109 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
110 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
111 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
112 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
113 * member has been initialized, doesn't do exception handling, and doesn't do
114 * memory allocation. Also doesn't check tag, assumes the caller has checked
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%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
136 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
137 pvStructInfo, pcbStructInfo);
139 if (!pvStructInfo && !pcbStructInfo)
141 SetLastError(ERROR_INVALID_PARAMETER);
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);
196 else if (pbEncoded[1] == 0x80)
198 FIXME("unimplemented for indefinite-length encoding\n");
199 SetLastError(CRYPT_E_ASN1_CORRUPT);
204 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
206 if (lenLen > sizeof(DWORD) + 1)
208 SetLastError(CRYPT_E_ASN1_LARGE);
211 else if (lenLen + 2 > cbEncoded)
213 SetLastError(CRYPT_E_ASN1_CORRUPT);
226 if (out + lenLen + 1 > cbEncoded)
228 SetLastError(CRYPT_E_ASN1_EOD);
241 /* Helper function to check *pcbStructInfo, set it to the required size, and
242 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
243 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
244 * pointer to the newly allocated memory.
246 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
247 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
252 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
254 if (pDecodePara && pDecodePara->pfnAlloc)
255 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
257 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
258 if (!*(BYTE **)pvStructInfo)
261 *pcbStructInfo = bytesNeeded;
263 else if (*pcbStructInfo < bytesNeeded)
265 *pcbStructInfo = bytesNeeded;
266 SetLastError(ERROR_MORE_DATA);
273 * The expected tag of the item. If tag is 0, decodeFunc is called
274 * regardless of the tag value seen.
276 * A sequence is decoded into a struct. The offset member is the
277 * offset of this item within that struct.
279 * The decoder function to use. If this is NULL, then the member isn't
280 * decoded, but minSize space is reserved for it.
282 * The minimum amount of space occupied after decoding. You must set this.
284 * If true, and the tag doesn't match the expected tag for this item,
285 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
286 * filled with 0 for this member.
287 * hasPointer, pointerOffset:
288 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
289 * the offset within the struct of the data pointer (or to the
290 * first data pointer, if more than one exist).
292 * Used by CRYPT_AsnDecodeSequence, not for your use.
294 struct AsnDecodeSequenceItem
298 CryptDecodeObjectExFunc decodeFunc;
306 /* Decodes the items in a sequence, where the items are described in items,
307 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
308 * pvStructInfo. nextData is a pointer to the memory location at which the
309 * first decoded item with a dynamic pointer should point.
310 * Upon decoding, *cbDecoded is the total number of bytes decoded.
312 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
313 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
314 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
318 DWORD i, decoded = 0;
319 const BYTE *ptr = pbEncoded;
321 for (i = 0, ret = TRUE; ret && i < cItem; i++)
323 if (cbEncoded - (ptr - pbEncoded) != 0)
327 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
330 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
332 if (ptr[0] == items[i].tag || !items[i].tag)
334 if (nextData && pvStructInfo && items[i].hasPointer)
336 TRACE("Setting next pointer to %p\n",
338 *(BYTE **)((BYTE *)pvStructInfo +
339 items[i].pointerOffset) = nextData;
341 if (items[i].decodeFunc)
344 TRACE("decoding item %d\n", i);
346 TRACE("sizing item %d\n", i);
347 ret = items[i].decodeFunc(dwCertEncodingType,
348 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
349 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
350 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
351 : NULL, &items[i].size);
354 if (nextData && items[i].hasPointer &&
355 items[i].size > items[i].minSize)
357 nextData += items[i].size - items[i].minSize;
358 /* align nextData to DWORD boundaries */
359 if (items[i].size % sizeof(DWORD))
360 nextData += sizeof(DWORD) - items[i].size %
363 /* Account for alignment padding */
364 if (items[i].size % sizeof(DWORD))
365 items[i].size += sizeof(DWORD) -
366 items[i].size % sizeof(DWORD);
367 ptr += 1 + nextItemLenBytes + nextItemLen;
368 decoded += 1 + nextItemLenBytes + nextItemLen;
370 else if (items[i].optional &&
371 GetLastError() == CRYPT_E_ASN1_BADTAG)
373 TRACE("skipping optional item %d\n", i);
374 items[i].size = items[i].minSize;
375 SetLastError(NOERROR);
379 TRACE("item %d failed: %08x\n", i,
384 decoded += 1 + nextItemLenBytes + nextItemLen;
385 items[i].size = items[i].minSize;
388 else if (items[i].optional)
390 TRACE("skipping optional item %d\n", i);
391 items[i].size = items[i].minSize;
395 TRACE("tag %02x doesn't match expected %02x\n",
396 ptr[0], items[i].tag);
397 SetLastError(CRYPT_E_ASN1_BADTAG);
402 else if (items[i].optional)
404 TRACE("missing optional item %d, skipping\n", i);
405 items[i].size = items[i].minSize;
409 TRACE("not enough bytes for item %d, failing\n", i);
410 SetLastError(CRYPT_E_ASN1_CORRUPT);
415 *cbDecoded = decoded;
419 /* This decodes an arbitrary sequence into a contiguous block of memory
420 * (basically, a struct.) Each element being decoded is described by a struct
421 * AsnDecodeSequenceItem, see above.
422 * startingPointer is an optional pointer to the first place where dynamic
423 * data will be stored. If you know the starting offset, you may pass it
424 * here. Otherwise, pass NULL, and one will be inferred from the items.
425 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
427 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
428 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
429 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
430 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
434 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
435 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
438 if (pbEncoded[0] == ASN_SEQUENCE)
442 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
444 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
445 const BYTE *ptr = pbEncoded + 1 + lenBytes;
447 cbEncoded -= 1 + lenBytes;
448 if (cbEncoded < dataLen)
450 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
452 SetLastError(CRYPT_E_ASN1_CORRUPT);
456 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
457 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
458 if (ret && cbDecoded != dataLen)
460 TRACE("expected %d decoded, got %d, failing\n", dataLen,
462 SetLastError(CRYPT_E_ASN1_CORRUPT);
467 DWORD i, bytesNeeded = 0, structSize = 0;
469 for (i = 0; i < cItem; i++)
471 bytesNeeded += items[i].size;
472 structSize += items[i].minSize;
475 *pcbStructInfo = bytesNeeded;
476 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
477 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
481 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
482 pvStructInfo = *(BYTE **)pvStructInfo;
484 nextData = (BYTE *)startingPointer;
486 nextData = (BYTE *)pvStructInfo + structSize;
487 memset(pvStructInfo, 0, structSize);
488 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
489 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
497 SetLastError(CRYPT_E_ASN1_BADTAG);
500 TRACE("returning %d (%08x)\n", ret, GetLastError());
505 * The expected tag of the entire encoded array (usually a variant
506 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
507 * regardless of the tag seen.
509 * used to decode each item in the array
511 * is the minimum size of each decoded item
513 * indicates whether each item has a dynamic pointer
515 * indicates the offset within itemSize at which the pointer exists
517 struct AsnArrayDescriptor
520 CryptDecodeObjectExFunc decodeFunc;
526 struct AsnArrayItemSize
532 /* Decodes an array of like types into a struct GenericArray.
533 * The layout and decoding of the array are described by a struct
534 * AsnArrayDescriptor.
536 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
537 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
538 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
539 void *startingPointer)
543 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
544 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
547 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
551 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
553 DWORD bytesNeeded, cItems = 0;
554 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
555 /* There can be arbitrarily many items, but there is often only one.
557 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
559 bytesNeeded = sizeof(struct GenericArray);
564 for (ptr = pbEncoded + 1 + lenBytes; ret &&
565 ptr - pbEncoded - 1 - lenBytes < dataLen; )
567 DWORD itemLenBytes, itemDataLen, size = 0;
569 itemLenBytes = GET_LEN_BYTES(ptr[1]);
570 /* Each item decoded may not tolerate extraneous bytes, so
571 * get the length of the next element and pass it directly.
573 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
576 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
577 1 + itemLenBytes + itemDataLen,
578 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
585 if (itemSizes != &itemSize)
586 itemSizes = CryptMemRealloc(itemSizes,
587 cItems * sizeof(struct AsnArrayItemSize));
592 cItems * sizeof(struct AsnArrayItemSize));
594 memcpy(itemSizes, &itemSize, sizeof(itemSize));
598 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
600 itemSizes[cItems - 1].size = size;
602 ret = CRYPT_GetLen(ptr,
603 cbEncoded - (ptr - pbEncoded), &nextLen);
605 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
615 *pcbStructInfo = bytesNeeded;
616 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
617 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
622 struct GenericArray *array;
624 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
625 pvStructInfo = *(BYTE **)pvStructInfo;
626 array = (struct GenericArray *)pvStructInfo;
627 array->cItems = cItems;
629 array->rgItems = startingPointer;
631 array->rgItems = (BYTE *)array +
632 sizeof(struct GenericArray);
633 nextData = (BYTE *)array->rgItems +
634 array->cItems * arrayDesc->itemSize;
635 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
636 i < cItems && ptr - pbEncoded - 1 - lenBytes <
639 if (arrayDesc->hasPointer)
640 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
641 + arrayDesc->pointerOffset) = nextData;
642 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
643 itemSizes[i].encodedLen,
644 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
645 array->rgItems + i * arrayDesc->itemSize,
651 nextData += itemSizes[i].size - arrayDesc->itemSize;
652 ret = CRYPT_GetLen(ptr,
653 cbEncoded - (ptr - pbEncoded), &nextLen);
655 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
660 if (itemSizes != &itemSize)
661 CryptMemFree(itemSizes);
666 SetLastError(CRYPT_E_ASN1_BADTAG);
672 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
673 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
674 * to CRYPT_E_ASN1_CORRUPT.
675 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
678 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
679 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
680 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
685 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
687 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
688 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
690 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
691 bytesNeeded += 1 + lenBytes + dataLen;
694 *pcbStructInfo = bytesNeeded;
695 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
696 pvStructInfo, pcbStructInfo, bytesNeeded)))
698 CRYPT_DER_BLOB *blob;
700 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
701 pvStructInfo = *(BYTE **)pvStructInfo;
702 blob = (CRYPT_DER_BLOB *)pvStructInfo;
703 blob->cbData = 1 + lenBytes + dataLen;
706 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
707 blob->pbData = (BYTE *)pbEncoded;
710 assert(blob->pbData);
711 memcpy(blob->pbData, pbEncoded, blob->cbData);
716 SetLastError(CRYPT_E_ASN1_CORRUPT);
724 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
725 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
726 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
727 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
731 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
732 pDecodePara, pvStructInfo, *pcbStructInfo);
734 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
737 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
738 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
739 pvStructInfo, pcbStructInfo);
740 if (ret && pvStructInfo)
742 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
749 for (i = 0; i < blob->cbData / 2; i++)
751 temp = blob->pbData[i];
752 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
753 blob->pbData[blob->cbData - i - 1] = temp;
757 TRACE("returning %d (%08x)\n", ret, GetLastError());
761 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
762 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
763 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
767 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
768 pDecodePara, pvStructInfo, *pcbStructInfo);
772 struct AsnDecodeSequenceItem items[] = {
773 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
774 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
775 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
776 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
777 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
778 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
779 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
780 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
781 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
782 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
785 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
786 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
787 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
788 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
789 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
793 SetLastError(STATUS_ACCESS_VIOLATION);
798 TRACE("Returning %d (%08x)\n", ret, GetLastError());
802 /* Internal function */
803 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
804 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
805 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
810 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
812 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
814 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
815 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
816 pvStructInfo, pcbStructInfo);
821 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
822 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
823 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
827 struct AsnDecodeSequenceItem items[] = {
828 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
829 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
830 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
831 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
834 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
835 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
836 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
840 /* Internal function */
841 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
842 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
843 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
848 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
850 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
852 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
853 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
854 pDecodePara, pvStructInfo, pcbStructInfo);
859 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
860 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
861 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
864 struct AsnDecodeSequenceItem items[] = {
865 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
866 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
867 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
868 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
869 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
870 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
871 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
872 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
873 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
874 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
876 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
877 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
879 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
880 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
882 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
883 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
884 FALSE, TRUE, offsetof(CERT_INFO,
885 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
886 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
887 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
888 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
889 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
890 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
891 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
892 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
893 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
894 offsetof(CERT_INFO, rgExtension), 0 },
897 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
898 pDecodePara, pvStructInfo, *pcbStructInfo);
900 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
901 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
902 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
903 if (ret && pvStructInfo)
907 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
908 info = *(CERT_INFO **)pvStructInfo;
910 info = (CERT_INFO *)pvStructInfo;
911 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
912 !info->Subject.cbData)
914 SetLastError(CRYPT_E_ASN1_CORRUPT);
915 /* Don't need to deallocate, because it should have failed on the
916 * first pass (and no memory was allocated.)
922 TRACE("Returning %d (%08x)\n", ret, GetLastError());
926 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
927 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
928 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
932 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
933 pDecodePara, pvStructInfo, *pcbStructInfo);
937 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
940 /* First try to decode it as a signed cert. */
941 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
942 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
943 (BYTE *)&signedCert, &size);
947 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
948 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
949 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
951 LocalFree(signedCert);
953 /* Failing that, try it as an unsigned cert */
957 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
958 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
959 pDecodePara, pvStructInfo, pcbStructInfo);
964 SetLastError(STATUS_ACCESS_VIOLATION);
969 TRACE("Returning %d (%08x)\n", ret, GetLastError());
973 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
974 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
975 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
978 struct AsnDecodeSequenceItem items[] = {
979 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
980 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
981 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
982 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
983 sizeof(FILETIME), FALSE, FALSE, 0 },
984 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
985 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
986 offsetof(CRL_ENTRY, rgExtension), 0 },
988 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
990 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
993 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
994 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
995 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
999 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1000 * been set prior to calling.
1002 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
1003 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1004 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1007 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1008 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1009 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1010 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1012 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1013 pDecodePara, pvStructInfo, *pcbStructInfo);
1015 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1016 pDecodePara, pvStructInfo, pcbStructInfo,
1017 entries ? entries->rgItems : NULL);
1018 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1022 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1023 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1024 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1026 struct AsnDecodeSequenceItem items[] = {
1027 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1028 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1029 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1030 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1031 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1032 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1033 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1035 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
1036 sizeof(FILETIME), FALSE, FALSE, 0 },
1037 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
1038 sizeof(FILETIME), TRUE, FALSE, 0 },
1039 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1040 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1041 offsetof(CRL_INFO, rgCRLEntry), 0 },
1042 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1043 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1044 offsetof(CRL_INFO, rgExtension), 0 },
1048 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1049 pDecodePara, pvStructInfo, *pcbStructInfo);
1051 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1052 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1053 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1055 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1059 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1060 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1061 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1065 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1066 pDecodePara, pvStructInfo, *pcbStructInfo);
1070 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1073 /* First try to decode it as a signed crl. */
1074 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1075 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1076 (BYTE *)&signedCrl, &size);
1080 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1081 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1082 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1083 pvStructInfo, pcbStructInfo);
1084 LocalFree(signedCrl);
1086 /* Failing that, try it as an unsigned crl */
1090 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1091 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1092 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1097 SetLastError(STATUS_ACCESS_VIOLATION);
1102 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1106 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1107 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1108 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1112 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1113 pDecodePara, pvStructInfo, *pcbStructInfo);
1115 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1119 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1121 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1122 DWORD bytesNeeded = sizeof(LPSTR);
1126 /* The largest possible string for the first two components
1127 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1132 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1133 pbEncoded[1 + lenBytes] / 40,
1134 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1136 bytesNeeded += strlen(firstTwo) + 1;
1137 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1138 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1140 /* large enough for ".4000000" */
1144 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1151 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1154 SetLastError(CRYPT_E_ASN1_CORRUPT);
1161 snprintf(str, sizeof(str), ".%d", val);
1162 bytesNeeded += strlen(str);
1167 *pcbStructInfo = bytesNeeded;
1168 else if (*pcbStructInfo < bytesNeeded)
1170 *pcbStructInfo = bytesNeeded;
1171 SetLastError(ERROR_MORE_DATA);
1179 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1182 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1183 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1185 pszObjId += strlen(pszObjId);
1186 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1187 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1191 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1200 sprintf(pszObjId, ".%d", val);
1201 pszObjId += strlen(pszObjId);
1205 *(LPSTR *)pvStructInfo = NULL;
1206 *pcbStructInfo = bytesNeeded;
1213 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1216 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1217 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1218 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1220 struct AsnDecodeSequenceItem items[] = {
1221 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1222 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1223 offsetof(CERT_EXTENSION, pszObjId), 0 },
1224 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1225 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1226 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1227 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1228 offsetof(CERT_EXTENSION, Value.pbData) },
1231 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1233 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1237 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1238 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1239 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1240 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1242 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1243 debugstr_a(ext->pszObjId));
1244 TRACE("returning %d (%08x)\n", ret, GetLastError());
1248 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1249 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1250 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1253 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1254 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1255 offsetof(CERT_EXTENSION, pszObjId) };
1256 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1258 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1259 pDecodePara, pvStructInfo, *pcbStructInfo);
1261 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1262 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1266 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1267 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1268 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1274 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1275 lpszStructType, pbEncoded, cbEncoded,
1276 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1277 if (ret && pvStructInfo)
1279 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1280 pcbStructInfo, *pcbStructInfo);
1283 CERT_EXTENSIONS *exts;
1285 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1286 pvStructInfo = *(BYTE **)pvStructInfo;
1287 exts = (CERT_EXTENSIONS *)pvStructInfo;
1288 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1289 sizeof(CERT_EXTENSIONS));
1290 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1291 lpszStructType, pbEncoded, cbEncoded,
1292 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1299 SetLastError(STATUS_ACCESS_VIOLATION);
1306 /* Warning: this assumes the address of value->Value.pbData is already set, in
1307 * order to avoid overwriting memory. (In some cases, it may change it, if it
1308 * doesn't copy anything to memory.) Be sure to set it correctly!
1310 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1311 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1312 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1316 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1318 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1320 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1321 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1323 switch (pbEncoded[0])
1325 case ASN_OCTETSTRING:
1326 valueType = CERT_RDN_OCTET_STRING;
1327 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1328 bytesNeeded += dataLen;
1330 case ASN_NUMERICSTRING:
1331 valueType = CERT_RDN_NUMERIC_STRING;
1332 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1333 bytesNeeded += dataLen;
1335 case ASN_PRINTABLESTRING:
1336 valueType = CERT_RDN_PRINTABLE_STRING;
1337 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1338 bytesNeeded += dataLen;
1341 valueType = CERT_RDN_IA5_STRING;
1342 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1343 bytesNeeded += dataLen;
1346 valueType = CERT_RDN_T61_STRING;
1347 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1348 bytesNeeded += dataLen;
1350 case ASN_VIDEOTEXSTRING:
1351 valueType = CERT_RDN_VIDEOTEX_STRING;
1352 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1353 bytesNeeded += dataLen;
1355 case ASN_GRAPHICSTRING:
1356 valueType = CERT_RDN_GRAPHIC_STRING;
1357 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1358 bytesNeeded += dataLen;
1360 case ASN_VISIBLESTRING:
1361 valueType = CERT_RDN_VISIBLE_STRING;
1362 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1363 bytesNeeded += dataLen;
1365 case ASN_GENERALSTRING:
1366 valueType = CERT_RDN_GENERAL_STRING;
1367 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1368 bytesNeeded += dataLen;
1370 case ASN_UNIVERSALSTRING:
1371 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1372 SetLastError(CRYPT_E_ASN1_BADTAG);
1375 valueType = CERT_RDN_BMP_STRING;
1376 bytesNeeded += dataLen;
1378 case ASN_UTF8STRING:
1379 valueType = CERT_RDN_UTF8_STRING;
1380 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1381 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1384 SetLastError(CRYPT_E_ASN1_BADTAG);
1389 *pcbStructInfo = bytesNeeded;
1390 else if (*pcbStructInfo < bytesNeeded)
1392 *pcbStructInfo = bytesNeeded;
1393 SetLastError(ERROR_MORE_DATA);
1398 *pcbStructInfo = bytesNeeded;
1399 value->dwValueType = valueType;
1404 assert(value->Value.pbData);
1405 switch (pbEncoded[0])
1407 case ASN_OCTETSTRING:
1408 case ASN_NUMERICSTRING:
1409 case ASN_PRINTABLESTRING:
1412 case ASN_VIDEOTEXSTRING:
1413 case ASN_GRAPHICSTRING:
1414 case ASN_VISIBLESTRING:
1415 case ASN_GENERALSTRING:
1416 value->Value.cbData = dataLen;
1419 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1420 memcpy(value->Value.pbData,
1421 pbEncoded + 1 + lenBytes, dataLen);
1423 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1429 LPWSTR str = (LPWSTR)value->Value.pbData;
1431 value->Value.cbData = dataLen;
1432 for (i = 0; i < dataLen / 2; i++)
1433 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1434 pbEncoded[1 + lenBytes + 2 * i + 1];
1437 case ASN_UTF8STRING:
1439 LPWSTR str = (LPWSTR)value->Value.pbData;
1441 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1442 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1443 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1450 value->Value.cbData = 0;
1451 value->Value.pbData = NULL;
1458 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1459 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1460 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1466 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1467 lpszStructType, pbEncoded, cbEncoded,
1468 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1469 if (ret && pvStructInfo)
1471 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1472 pcbStructInfo, *pcbStructInfo);
1475 CERT_NAME_VALUE *value;
1477 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1478 pvStructInfo = *(BYTE **)pvStructInfo;
1479 value = (CERT_NAME_VALUE *)pvStructInfo;
1480 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1481 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1482 lpszStructType, pbEncoded, cbEncoded,
1483 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1490 SetLastError(STATUS_ACCESS_VIOLATION);
1497 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1498 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1499 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1500 void *pvStructInfo, DWORD *pcbStructInfo)
1504 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1506 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1508 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1509 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1511 switch (pbEncoded[0])
1513 case ASN_NUMERICSTRING:
1514 valueType = CERT_RDN_NUMERIC_STRING;
1515 bytesNeeded += dataLen * 2;
1517 case ASN_PRINTABLESTRING:
1518 valueType = CERT_RDN_PRINTABLE_STRING;
1519 bytesNeeded += dataLen * 2;
1522 valueType = CERT_RDN_IA5_STRING;
1523 bytesNeeded += dataLen * 2;
1526 valueType = CERT_RDN_T61_STRING;
1527 bytesNeeded += dataLen * 2;
1529 case ASN_VIDEOTEXSTRING:
1530 valueType = CERT_RDN_VIDEOTEX_STRING;
1531 bytesNeeded += dataLen * 2;
1533 case ASN_GRAPHICSTRING:
1534 valueType = CERT_RDN_GRAPHIC_STRING;
1535 bytesNeeded += dataLen * 2;
1537 case ASN_VISIBLESTRING:
1538 valueType = CERT_RDN_VISIBLE_STRING;
1539 bytesNeeded += dataLen * 2;
1541 case ASN_GENERALSTRING:
1542 valueType = CERT_RDN_GENERAL_STRING;
1543 bytesNeeded += dataLen * 2;
1545 case ASN_UNIVERSALSTRING:
1546 valueType = CERT_RDN_UNIVERSAL_STRING;
1547 bytesNeeded += dataLen / 2;
1550 valueType = CERT_RDN_BMP_STRING;
1551 bytesNeeded += dataLen;
1553 case ASN_UTF8STRING:
1554 valueType = CERT_RDN_UTF8_STRING;
1555 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1556 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1559 SetLastError(CRYPT_E_ASN1_BADTAG);
1564 *pcbStructInfo = bytesNeeded;
1565 else if (*pcbStructInfo < bytesNeeded)
1567 *pcbStructInfo = bytesNeeded;
1568 SetLastError(ERROR_MORE_DATA);
1573 *pcbStructInfo = bytesNeeded;
1574 value->dwValueType = valueType;
1578 LPWSTR str = (LPWSTR)value->Value.pbData;
1580 assert(value->Value.pbData);
1581 switch (pbEncoded[0])
1583 case ASN_NUMERICSTRING:
1584 case ASN_PRINTABLESTRING:
1587 case ASN_VIDEOTEXSTRING:
1588 case ASN_GRAPHICSTRING:
1589 case ASN_VISIBLESTRING:
1590 case ASN_GENERALSTRING:
1591 value->Value.cbData = dataLen * 2;
1592 for (i = 0; i < dataLen; i++)
1593 str[i] = pbEncoded[1 + lenBytes + i];
1595 case ASN_UNIVERSALSTRING:
1596 value->Value.cbData = dataLen / 2;
1597 for (i = 0; i < dataLen / 4; i++)
1598 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1599 | pbEncoded[1 + lenBytes + 2 * i + 3];
1602 value->Value.cbData = dataLen;
1603 for (i = 0; i < dataLen / 2; i++)
1604 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1605 pbEncoded[1 + lenBytes + 2 * i + 1];
1607 case ASN_UTF8STRING:
1608 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1609 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1610 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1616 value->Value.cbData = 0;
1617 value->Value.pbData = NULL;
1624 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1625 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1626 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1632 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1633 lpszStructType, pbEncoded, cbEncoded,
1634 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1635 if (ret && pvStructInfo)
1637 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1638 pcbStructInfo, *pcbStructInfo);
1641 CERT_NAME_VALUE *value;
1643 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1644 pvStructInfo = *(BYTE **)pvStructInfo;
1645 value = (CERT_NAME_VALUE *)pvStructInfo;
1646 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1647 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1648 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1649 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1656 SetLastError(STATUS_ACCESS_VIOLATION);
1663 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1664 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1665 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1668 struct AsnDecodeSequenceItem items[] = {
1669 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1670 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1671 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1672 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1673 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1674 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1676 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1678 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1679 pvStructInfo, *pcbStructInfo);
1682 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1683 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1684 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1685 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1688 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1689 debugstr_a(attr->pszObjId));
1690 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1692 TRACE("returning %d (%08x)\n", ret, GetLastError());
1696 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1697 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1698 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1701 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1702 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1703 offsetof(CERT_RDN_ATTR, pszObjId) };
1704 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1706 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1707 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1711 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1712 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1713 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1719 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1720 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1721 offsetof(CERT_RDN, rgRDNAttr) };
1723 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1724 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1728 SetLastError(STATUS_ACCESS_VIOLATION);
1735 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
1736 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1737 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1740 struct AsnDecodeSequenceItem items[] = {
1741 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1742 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1743 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1744 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1745 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1746 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1748 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1750 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1751 pvStructInfo, *pcbStructInfo);
1754 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1755 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1756 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1757 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1760 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1761 debugstr_a(attr->pszObjId));
1762 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1764 TRACE("returning %d (%08x)\n", ret, GetLastError());
1768 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
1769 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1770 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1773 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1774 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1775 offsetof(CERT_RDN_ATTR, pszObjId) };
1776 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1778 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1779 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1783 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1784 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1785 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1791 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1792 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1793 offsetof(CERT_RDN, rgRDNAttr) };
1795 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1796 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1800 SetLastError(STATUS_ACCESS_VIOLATION);
1807 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1808 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1809 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1812 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1814 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1815 pDecodePara, pvStructInfo, *pcbStructInfo);
1817 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1818 bytesNeeded += cbEncoded;
1820 *pcbStructInfo = bytesNeeded;
1821 else if (*pcbStructInfo < bytesNeeded)
1823 SetLastError(ERROR_MORE_DATA);
1824 *pcbStructInfo = bytesNeeded;
1829 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1831 *pcbStructInfo = bytesNeeded;
1832 blob->cbData = cbEncoded;
1833 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1834 blob->pbData = (LPBYTE)pbEncoded;
1837 assert(blob->pbData);
1838 memcpy(blob->pbData, pbEncoded, blob->cbData);
1844 static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType,
1845 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1846 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1849 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1850 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB), TRUE,
1851 offsetof(CRYPT_DER_BLOB, pbData) };
1852 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1854 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1855 pDecodePara, pvStructInfo, *pcbStructInfo);
1857 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1858 pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
1862 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1863 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1864 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1870 struct AsnDecodeSequenceItem items[] = {
1871 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1872 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1873 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1874 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1875 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1876 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1878 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1880 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1881 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1882 pDecodePara, pvStructInfo, pcbStructInfo, attr ? attr->pszObjId :
1887 SetLastError(STATUS_ACCESS_VIOLATION);
1890 TRACE("returning %d\n", ret);
1894 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal(
1895 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1896 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1897 void *pvStructInfo, DWORD *pcbStructInfo)
1899 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1900 CRYPT_AsnDecodePKCSAttribute, sizeof(CRYPT_ATTRIBUTE), TRUE,
1901 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
1902 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1905 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1906 pDecodePara, pvStructInfo, pcbStructInfo, attrs ? attrs->rgAttr :
1911 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
1912 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1913 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1917 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1918 pDecodePara, pvStructInfo, *pcbStructInfo);
1924 if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1925 lpszStructType, pbEncoded, cbEncoded,
1926 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1929 *pcbStructInfo = bytesNeeded;
1930 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1931 pvStructInfo, pcbStructInfo, bytesNeeded)))
1933 PCRYPT_ATTRIBUTES attrs;
1935 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1936 pvStructInfo = *(BYTE **)pvStructInfo;
1937 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1938 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
1939 sizeof(CRYPT_ATTRIBUTES));
1940 ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1941 lpszStructType, pbEncoded, cbEncoded,
1942 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1949 SetLastError(STATUS_ACCESS_VIOLATION);
1952 TRACE("returning %d\n", ret);
1956 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1957 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1958 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1960 CRYPT_ALGORITHM_IDENTIFIER *algo =
1961 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1963 struct AsnDecodeSequenceItem items[] = {
1964 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1965 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1966 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1967 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1968 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1969 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1972 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1973 pDecodePara, pvStructInfo, *pcbStructInfo);
1975 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1976 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1977 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1978 if (ret && pvStructInfo)
1980 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1981 debugstr_a(algo->pszObjId));
1986 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1987 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1988 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1991 struct AsnDecodeSequenceItem items[] = {
1992 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1993 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1994 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1995 Algorithm.pszObjId) },
1996 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1997 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1998 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2000 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2002 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2003 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2004 pDecodePara, pvStructInfo, pcbStructInfo, info ?
2005 info->Algorithm.Parameters.pbData : NULL);
2009 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2010 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2011 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2019 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2020 lpszStructType, pbEncoded, cbEncoded,
2021 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2024 *pcbStructInfo = bytesNeeded;
2025 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2026 pvStructInfo, pcbStructInfo, bytesNeeded)))
2028 PCERT_PUBLIC_KEY_INFO info;
2030 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2031 pvStructInfo = *(BYTE **)pvStructInfo;
2032 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2033 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2034 sizeof(CERT_PUBLIC_KEY_INFO);
2035 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2036 lpszStructType, pbEncoded, cbEncoded,
2037 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2044 SetLastError(STATUS_ACCESS_VIOLATION);
2051 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2052 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2053 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2059 SetLastError(CRYPT_E_ASN1_CORRUPT);
2062 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2064 SetLastError(CRYPT_E_ASN1_CORRUPT);
2067 if (pbEncoded[1] > 1)
2069 SetLastError(CRYPT_E_ASN1_CORRUPT);
2074 *pcbStructInfo = sizeof(BOOL);
2077 else if (*pcbStructInfo < sizeof(BOOL))
2079 *pcbStructInfo = sizeof(BOOL);
2080 SetLastError(ERROR_MORE_DATA);
2085 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2088 TRACE("returning %d (%08x)\n", ret, GetLastError());
2092 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
2093 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2094 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2096 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2097 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2100 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2101 pDecodePara, pvStructInfo, *pcbStructInfo);
2105 SetLastError(CRYPT_E_ASN1_CORRUPT);
2108 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
2110 SetLastError(CRYPT_E_ASN1_BADTAG);
2113 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2114 if (1 + lenBytes > cbEncoded)
2116 SetLastError(CRYPT_E_ASN1_CORRUPT);
2119 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2121 switch (pbEncoded[0] & ASN_TYPE_MASK)
2123 case 1: /* rfc822Name */
2124 case 2: /* dNSName */
2125 case 6: /* uniformResourceIdentifier */
2126 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2128 case 7: /* iPAddress */
2129 bytesNeeded += dataLen;
2131 case 8: /* registeredID */
2132 /* FIXME: decode as OID */
2133 case 0: /* otherName */
2134 case 4: /* directoryName */
2136 SetLastError(CRYPT_E_ASN1_BADTAG);
2139 case 3: /* x400Address, unimplemented */
2140 case 5: /* ediPartyName, unimplemented */
2141 SetLastError(CRYPT_E_ASN1_BADTAG);
2145 SetLastError(CRYPT_E_ASN1_CORRUPT);
2151 *pcbStructInfo = bytesNeeded;
2152 else if (*pcbStructInfo < bytesNeeded)
2154 *pcbStructInfo = bytesNeeded;
2155 SetLastError(ERROR_MORE_DATA);
2160 *pcbStructInfo = bytesNeeded;
2161 /* MS used values one greater than the asn1 ones.. sigh */
2162 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2163 switch (pbEncoded[0] & ASN_TYPE_MASK)
2165 case 1: /* rfc822Name */
2166 case 2: /* dNSName */
2167 case 6: /* uniformResourceIdentifier */
2171 for (i = 0; i < dataLen; i++)
2172 entry->u.pwszURL[i] =
2173 (WCHAR)pbEncoded[1 + lenBytes + i];
2174 entry->u.pwszURL[i] = 0;
2175 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2176 debugstr_w(entry->u.pwszURL));
2179 case 7: /* iPAddress */
2180 /* The next data pointer is in the pwszURL spot, that is,
2181 * the first 4 bytes. Need to move it to the next spot.
2183 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2184 entry->u.IPAddress.cbData = dataLen;
2185 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2195 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2196 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2197 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2200 struct AsnArrayDescriptor arrayDesc = { 0,
2201 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2202 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2203 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2205 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2206 pDecodePara, pvStructInfo, *pcbStructInfo);
2209 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2210 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2211 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2215 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2216 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2217 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2223 struct AsnDecodeSequenceItem items[] = {
2224 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2225 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2226 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2227 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2228 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2229 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2230 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2231 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2232 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2233 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2234 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2237 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2238 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2239 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2243 SetLastError(STATUS_ACCESS_VIOLATION);
2250 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2251 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2252 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2258 struct AsnDecodeSequenceItem items[] = {
2259 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2260 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2261 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2262 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2263 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2264 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2265 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2266 AuthorityCertIssuer.rgAltEntry), 0 },
2267 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2268 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2269 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2270 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2271 AuthorityCertSerialNumber.pbData), 0 },
2274 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2275 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2276 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2280 SetLastError(STATUS_ACCESS_VIOLATION);
2287 static BOOL WINAPI CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType,
2288 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2289 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2294 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2295 pDecodePara, pvStructInfo, *pcbStructInfo);
2297 /* The caller has already checked the tag, no need to check it again.
2298 * Check the outer length is valid by calling CRYPT_GetLen:
2300 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2302 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2305 pbEncoded += 1 + lenBytes;
2306 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2307 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2309 ret = CRYPT_AsnDecodeCopyBytes(dwCertEncodingType, NULL,
2310 pbEncoded, dataLen, dwFlags, pDecodePara, pvStructInfo,
2317 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfoInternal(
2318 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2319 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2320 void *pvStructInfo, DWORD *pcbStructInfo)
2322 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2323 struct AsnDecodeSequenceItem items[] = {
2324 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2325 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
2326 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2327 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2328 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2329 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2330 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2333 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2334 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2335 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->pszObjId : NULL);
2338 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2339 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2340 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2344 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2345 pDecodePara, pvStructInfo, *pcbStructInfo);
2349 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2350 lpszStructType, pbEncoded, cbEncoded,
2351 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
2352 if (ret && pvStructInfo)
2354 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2355 pcbStructInfo, *pcbStructInfo);
2358 CRYPT_CONTENT_INFO *info;
2360 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2361 pvStructInfo = *(BYTE **)pvStructInfo;
2362 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2363 info->pszObjId = (LPSTR)((BYTE *)info +
2364 sizeof(CRYPT_CONTENT_INFO));
2365 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2366 lpszStructType, pbEncoded, cbEncoded,
2367 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2374 SetLastError(STATUS_ACCESS_VIOLATION);
2380 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2381 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2382 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2385 struct AsnDecodeSequenceItem items[] = {
2386 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version), CRYPT_AsnDecodeInt,
2387 sizeof(DWORD), FALSE, FALSE, 0, 0 },
2388 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2389 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2390 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2392 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2393 CRYPT_AsnDecodePKCSContentInfoInternal,
2394 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2395 ContentInfo.pszObjId), 0 },
2396 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2397 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2398 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2401 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
2402 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2403 pDecodePara, digestedData, pcbDigestedData, NULL);
2407 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2408 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2409 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2413 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2414 pDecodePara, pvStructInfo, *pcbStructInfo);
2418 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2419 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2420 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2422 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2423 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2427 SetLastError(STATUS_ACCESS_VIOLATION);
2434 struct PATH_LEN_CONSTRAINT
2436 BOOL fPathLenConstraint;
2437 DWORD dwPathLenConstraint;
2440 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2441 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2442 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2446 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2447 pvStructInfo, *pcbStructInfo);
2451 if (pbEncoded[0] == ASN_INTEGER)
2453 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2456 *pcbStructInfo = bytesNeeded;
2457 else if (*pcbStructInfo < bytesNeeded)
2459 SetLastError(ERROR_MORE_DATA);
2460 *pcbStructInfo = bytesNeeded;
2465 struct PATH_LEN_CONSTRAINT *constraint =
2466 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2467 DWORD size = sizeof(constraint->dwPathLenConstraint);
2469 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2470 pbEncoded, cbEncoded, 0, NULL,
2471 &constraint->dwPathLenConstraint, &size);
2473 constraint->fPathLenConstraint = TRUE;
2474 TRACE("got an int, dwPathLenConstraint is %d\n",
2475 constraint->dwPathLenConstraint);
2480 SetLastError(CRYPT_E_ASN1_CORRUPT);
2484 TRACE("returning %d (%08x)\n", ret, GetLastError());
2488 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2489 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2490 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2493 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2494 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2495 offsetof(CERT_NAME_BLOB, pbData) };
2496 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2498 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2499 pDecodePara, pvStructInfo, *pcbStructInfo);
2501 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2502 pDecodePara, pvStructInfo, pcbStructInfo,
2503 entries ? entries->rgItems : NULL);
2504 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2508 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2509 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2510 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2516 struct AsnDecodeSequenceItem items[] = {
2517 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2518 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2519 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2520 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2521 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2522 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2523 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2524 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2525 sizeof(struct GenericArray), TRUE, TRUE,
2526 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2529 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2530 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2531 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2535 SetLastError(STATUS_ACCESS_VIOLATION);
2542 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2543 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2544 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2550 struct AsnDecodeSequenceItem items[] = {
2551 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2552 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2553 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2554 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2555 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2558 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2559 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2560 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2564 SetLastError(STATUS_ACCESS_VIOLATION);
2571 #define RSA1_MAGIC 0x31415352
2573 struct DECODED_RSA_PUB_KEY
2576 CRYPT_INTEGER_BLOB modulus;
2579 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2580 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2581 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2587 struct AsnDecodeSequenceItem items[] = {
2588 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2589 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2590 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2592 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2593 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2595 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2598 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2599 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2600 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2603 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2604 decodedKey->modulus.cbData;
2608 *pcbStructInfo = bytesNeeded;
2611 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2612 pvStructInfo, pcbStructInfo, bytesNeeded)))
2615 RSAPUBKEY *rsaPubKey;
2617 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2618 pvStructInfo = *(BYTE **)pvStructInfo;
2619 hdr = (BLOBHEADER *)pvStructInfo;
2620 hdr->bType = PUBLICKEYBLOB;
2621 hdr->bVersion = CUR_BLOB_VERSION;
2623 hdr->aiKeyAlg = CALG_RSA_KEYX;
2624 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2625 sizeof(BLOBHEADER));
2626 rsaPubKey->magic = RSA1_MAGIC;
2627 rsaPubKey->pubexp = decodedKey->pubexp;
2628 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2629 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2630 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2631 decodedKey->modulus.cbData);
2633 LocalFree(decodedKey);
2638 SetLastError(STATUS_ACCESS_VIOLATION);
2645 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2646 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2647 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2650 DWORD bytesNeeded, dataLen;
2652 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2653 pDecodePara, pvStructInfo, *pcbStructInfo);
2655 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2657 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2658 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2660 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2662 *pcbStructInfo = bytesNeeded;
2663 else if (*pcbStructInfo < bytesNeeded)
2665 SetLastError(ERROR_MORE_DATA);
2666 *pcbStructInfo = bytesNeeded;
2671 CRYPT_DATA_BLOB *blob;
2672 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2674 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2675 blob->cbData = dataLen;
2676 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2677 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2680 assert(blob->pbData);
2682 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2690 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2691 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2692 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2696 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2697 pDecodePara, pvStructInfo, *pcbStructInfo);
2705 SetLastError(CRYPT_E_ASN1_CORRUPT);
2708 else if (pbEncoded[0] != ASN_OCTETSTRING)
2710 SetLastError(CRYPT_E_ASN1_BADTAG);
2713 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2714 lpszStructType, pbEncoded, cbEncoded,
2715 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2718 *pcbStructInfo = bytesNeeded;
2719 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2720 pvStructInfo, pcbStructInfo, bytesNeeded)))
2722 CRYPT_DATA_BLOB *blob;
2724 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2725 pvStructInfo = *(BYTE **)pvStructInfo;
2726 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2727 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2728 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2729 lpszStructType, pbEncoded, cbEncoded,
2730 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2737 SetLastError(STATUS_ACCESS_VIOLATION);
2744 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2745 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2746 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2750 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2751 pDecodePara, pvStructInfo, *pcbStructInfo);
2753 if (pbEncoded[0] == ASN_BITSTRING)
2755 DWORD bytesNeeded, dataLen;
2757 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2759 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2760 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2762 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2764 *pcbStructInfo = bytesNeeded;
2765 else if (*pcbStructInfo < bytesNeeded)
2767 *pcbStructInfo = bytesNeeded;
2768 SetLastError(ERROR_MORE_DATA);
2773 CRYPT_BIT_BLOB *blob;
2775 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2776 blob->cbData = dataLen - 1;
2777 blob->cUnusedBits = *(pbEncoded + 1 +
2778 GET_LEN_BYTES(pbEncoded[1]));
2779 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2781 blob->pbData = (BYTE *)pbEncoded + 2 +
2782 GET_LEN_BYTES(pbEncoded[1]);
2786 assert(blob->pbData);
2789 BYTE mask = 0xff << blob->cUnusedBits;
2791 memcpy(blob->pbData, pbEncoded + 2 +
2792 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2793 blob->pbData[blob->cbData - 1] &= mask;
2801 SetLastError(CRYPT_E_ASN1_BADTAG);
2804 TRACE("returning %d (%08x)\n", ret, GetLastError());
2808 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2809 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2810 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2814 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2815 pDecodePara, pvStructInfo, pcbStructInfo);
2821 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2822 lpszStructType, pbEncoded, cbEncoded,
2823 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2826 *pcbStructInfo = bytesNeeded;
2827 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2828 pvStructInfo, pcbStructInfo, bytesNeeded)))
2830 CRYPT_BIT_BLOB *blob;
2832 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2833 pvStructInfo = *(BYTE **)pvStructInfo;
2834 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2835 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2836 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2837 lpszStructType, pbEncoded, cbEncoded,
2838 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2845 SetLastError(STATUS_ACCESS_VIOLATION);
2849 TRACE("returning %d (%08x)\n", ret, GetLastError());
2853 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2854 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2855 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2861 *pcbStructInfo = sizeof(int);
2866 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2867 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2868 DWORD size = sizeof(buf);
2870 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2871 if (pbEncoded[0] != ASN_INTEGER)
2873 SetLastError(CRYPT_E_ASN1_BADTAG);
2877 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2878 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
2882 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2883 pvStructInfo, pcbStructInfo, sizeof(int))))
2887 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2888 pvStructInfo = *(BYTE **)pvStructInfo;
2889 if (blob->pbData[blob->cbData - 1] & 0x80)
2891 /* initialize to a negative value to sign-extend */
2896 for (i = 0; i < blob->cbData; i++)
2899 val |= blob->pbData[blob->cbData - i - 1];
2901 memcpy(pvStructInfo, &val, sizeof(int));
2904 else if (GetLastError() == ERROR_MORE_DATA)
2905 SetLastError(CRYPT_E_ASN1_LARGE);
2909 SetLastError(STATUS_ACCESS_VIOLATION);
2916 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2917 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2918 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2921 DWORD bytesNeeded, dataLen;
2923 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2925 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2927 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2929 *pcbStructInfo = bytesNeeded;
2930 else if (*pcbStructInfo < bytesNeeded)
2932 *pcbStructInfo = bytesNeeded;
2933 SetLastError(ERROR_MORE_DATA);
2938 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2940 blob->cbData = dataLen;
2941 assert(blob->pbData);
2946 for (i = 0; i < blob->cbData; i++)
2948 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2957 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2958 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2959 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2967 if (pbEncoded[0] != ASN_INTEGER)
2969 SetLastError(CRYPT_E_ASN1_BADTAG);
2973 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2974 lpszStructType, pbEncoded, cbEncoded,
2975 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
2979 *pcbStructInfo = bytesNeeded;
2980 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2981 pvStructInfo, pcbStructInfo, bytesNeeded)))
2983 CRYPT_INTEGER_BLOB *blob;
2985 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2986 pvStructInfo = *(BYTE **)pvStructInfo;
2987 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2988 blob->pbData = (BYTE *)pvStructInfo +
2989 sizeof(CRYPT_INTEGER_BLOB);
2990 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2991 lpszStructType, pbEncoded, cbEncoded,
2992 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2999 SetLastError(STATUS_ACCESS_VIOLATION);
3006 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
3007 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3008 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3009 void *pvStructInfo, DWORD *pcbStructInfo)
3013 if (pbEncoded[0] == ASN_INTEGER)
3015 DWORD bytesNeeded, dataLen;
3017 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3019 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3021 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3023 *pcbStructInfo = bytesNeeded;
3024 else if (*pcbStructInfo < bytesNeeded)
3026 *pcbStructInfo = bytesNeeded;
3027 SetLastError(ERROR_MORE_DATA);
3032 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3034 blob->cbData = dataLen;
3035 assert(blob->pbData);
3036 /* remove leading zero byte if it exists */
3037 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3046 for (i = 0; i < blob->cbData; i++)
3048 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3057 SetLastError(CRYPT_E_ASN1_BADTAG);
3063 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3064 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3065 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3073 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3074 lpszStructType, pbEncoded, cbEncoded,
3075 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
3078 *pcbStructInfo = bytesNeeded;
3079 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3080 pvStructInfo, pcbStructInfo, bytesNeeded)))
3082 CRYPT_INTEGER_BLOB *blob;
3084 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3085 pvStructInfo = *(BYTE **)pvStructInfo;
3086 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3087 blob->pbData = (BYTE *)pvStructInfo +
3088 sizeof(CRYPT_INTEGER_BLOB);
3089 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3090 lpszStructType, pbEncoded, cbEncoded,
3091 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3098 SetLastError(STATUS_ACCESS_VIOLATION);
3105 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3106 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3107 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3113 *pcbStructInfo = sizeof(int);
3118 if (pbEncoded[0] == ASN_ENUMERATED)
3120 unsigned int val = 0, i;
3124 SetLastError(CRYPT_E_ASN1_EOD);
3127 else if (pbEncoded[1] == 0)
3129 SetLastError(CRYPT_E_ASN1_CORRUPT);
3134 /* A little strange looking, but we have to accept a sign byte:
3135 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3136 * assuming a small length is okay here, it has to be in short
3139 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3141 SetLastError(CRYPT_E_ASN1_LARGE);
3144 for (i = 0; i < pbEncoded[1]; i++)
3147 val |= pbEncoded[2 + i];
3149 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3150 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3152 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3153 pvStructInfo = *(BYTE **)pvStructInfo;
3154 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3160 SetLastError(CRYPT_E_ASN1_BADTAG);
3166 SetLastError(STATUS_ACCESS_VIOLATION);
3173 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3176 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3181 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3183 if (!isdigit(*(pbEncoded))) \
3185 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3191 (word) += *(pbEncoded)++ - '0'; \
3196 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3197 SYSTEMTIME *sysTime)
3204 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3206 WORD hours, minutes = 0;
3207 BYTE sign = *pbEncoded++;
3210 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3211 if (ret && hours >= 24)
3213 SetLastError(CRYPT_E_ASN1_CORRUPT);
3218 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3219 if (ret && minutes >= 60)
3221 SetLastError(CRYPT_E_ASN1_CORRUPT);
3229 sysTime->wHour += hours;
3230 sysTime->wMinute += minutes;
3234 if (hours > sysTime->wHour)
3237 sysTime->wHour = 24 - (hours - sysTime->wHour);
3240 sysTime->wHour -= hours;
3241 if (minutes > sysTime->wMinute)
3244 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3247 sysTime->wMinute -= minutes;
3254 SetLastError(STATUS_ACCESS_VIOLATION);
3261 #define MIN_ENCODED_TIME_LENGTH 10
3263 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3264 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3265 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3271 *pcbStructInfo = sizeof(FILETIME);
3277 if (pbEncoded[0] == ASN_UTCTIME)
3281 SetLastError(CRYPT_E_ASN1_EOD);
3284 else if (pbEncoded[1] > 0x7f)
3286 /* long-form date strings really can't be valid */
3287 SetLastError(CRYPT_E_ASN1_CORRUPT);
3292 SYSTEMTIME sysTime = { 0 };
3293 BYTE len = pbEncoded[1];
3295 if (len < MIN_ENCODED_TIME_LENGTH)
3297 SetLastError(CRYPT_E_ASN1_CORRUPT);
3303 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3304 if (sysTime.wYear >= 50)
3305 sysTime.wYear += 1900;
3307 sysTime.wYear += 2000;
3308 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3309 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3310 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3311 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3314 if (len >= 2 && isdigit(*pbEncoded) &&
3315 isdigit(*(pbEncoded + 1)))
3316 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3318 else if (isdigit(*pbEncoded))
3319 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3322 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3325 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3326 pDecodePara, pvStructInfo, pcbStructInfo,
3329 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3330 pvStructInfo = *(BYTE **)pvStructInfo;
3331 ret = SystemTimeToFileTime(&sysTime,
3332 (FILETIME *)pvStructInfo);
3339 SetLastError(CRYPT_E_ASN1_BADTAG);
3345 SetLastError(STATUS_ACCESS_VIOLATION);
3352 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3353 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3354 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3360 *pcbStructInfo = sizeof(FILETIME);
3366 if (pbEncoded[0] == ASN_GENERALTIME)
3370 SetLastError(CRYPT_E_ASN1_EOD);
3373 else if (pbEncoded[1] > 0x7f)
3375 /* long-form date strings really can't be valid */
3376 SetLastError(CRYPT_E_ASN1_CORRUPT);
3381 BYTE len = pbEncoded[1];
3383 if (len < MIN_ENCODED_TIME_LENGTH)
3385 SetLastError(CRYPT_E_ASN1_CORRUPT);
3390 SYSTEMTIME sysTime = { 0 };
3393 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3394 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3395 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3396 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3399 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3402 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3404 if (ret && len > 0 && (*pbEncoded == '.' ||
3411 /* workaround macro weirdness */
3412 digits = min(len, 3);
3413 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3414 sysTime.wMilliseconds);
3417 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3420 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3421 pDecodePara, pvStructInfo, pcbStructInfo,
3424 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3425 pvStructInfo = *(BYTE **)pvStructInfo;
3426 ret = SystemTimeToFileTime(&sysTime,
3427 (FILETIME *)pvStructInfo);
3434 SetLastError(CRYPT_E_ASN1_BADTAG);
3440 SetLastError(STATUS_ACCESS_VIOLATION);
3447 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3448 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3449 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3455 if (pbEncoded[0] == ASN_UTCTIME)
3456 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3457 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3459 else if (pbEncoded[0] == ASN_GENERALTIME)
3460 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3461 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3462 pvStructInfo, pcbStructInfo);
3465 SetLastError(CRYPT_E_ASN1_BADTAG);
3471 SetLastError(STATUS_ACCESS_VIOLATION);
3478 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3479 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3480 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3486 if (pbEncoded[0] == ASN_SEQUENCEOF)
3488 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3490 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3495 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3496 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3498 ptr = pbEncoded + 1 + lenBytes;
3499 remainingLen = dataLen;
3500 while (ret && remainingLen)
3504 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3507 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3509 remainingLen -= 1 + nextLenBytes + nextLen;
3510 ptr += 1 + nextLenBytes + nextLen;
3511 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3512 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3513 bytesNeeded += 1 + nextLenBytes + nextLen;
3519 CRYPT_SEQUENCE_OF_ANY *seq;
3523 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3524 pvStructInfo, pcbStructInfo, bytesNeeded)))
3526 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3527 pvStructInfo = *(BYTE **)pvStructInfo;
3528 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3529 seq->cValue = cValue;
3530 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3532 nextPtr = (BYTE *)seq->rgValue +
3533 cValue * sizeof(CRYPT_DER_BLOB);
3534 ptr = pbEncoded + 1 + lenBytes;
3535 remainingLen = dataLen;
3537 while (ret && remainingLen)
3541 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3544 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3546 seq->rgValue[i].cbData = 1 + nextLenBytes +
3548 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3549 seq->rgValue[i].pbData = (BYTE *)ptr;
3552 seq->rgValue[i].pbData = nextPtr;
3553 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3555 nextPtr += 1 + nextLenBytes + nextLen;
3557 remainingLen -= 1 + nextLenBytes + nextLen;
3558 ptr += 1 + nextLenBytes + nextLen;
3568 SetLastError(CRYPT_E_ASN1_BADTAG);
3574 SetLastError(STATUS_ACCESS_VIOLATION);
3581 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3582 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3583 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3587 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3589 DWORD bytesNeeded, dataLen;
3591 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3593 struct AsnArrayDescriptor arrayDesc = {
3594 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3595 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3596 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3597 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3603 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3604 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3605 0, NULL, NULL, &nameLen, NULL);
3606 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3609 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3611 *pcbStructInfo = bytesNeeded;
3612 else if (*pcbStructInfo < bytesNeeded)
3614 *pcbStructInfo = bytesNeeded;
3615 SetLastError(ERROR_MORE_DATA);
3620 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3624 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3625 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3626 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3627 0, NULL, &name->u.FullName, pcbStructInfo,
3628 name->u.FullName.rgAltEntry);
3631 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3637 SetLastError(CRYPT_E_ASN1_BADTAG);
3643 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3644 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3645 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3647 struct AsnDecodeSequenceItem items[] = {
3648 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3649 DistPointName), CRYPT_AsnDecodeDistPointName,
3650 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3651 DistPointName.u.FullName.rgAltEntry), 0 },
3652 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3653 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3654 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3655 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3656 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3657 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3661 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3662 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3663 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3667 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3668 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3669 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3673 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3674 pDecodePara, pvStructInfo, *pcbStructInfo);
3678 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3679 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3680 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3682 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3683 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3687 SetLastError(STATUS_ACCESS_VIOLATION);
3694 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3695 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3696 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3700 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3701 pDecodePara, pvStructInfo, *pcbStructInfo);
3705 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3706 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3708 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3709 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3713 SetLastError(STATUS_ACCESS_VIOLATION);
3720 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3721 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3722 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3726 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3727 pDecodePara, pvStructInfo, *pcbStructInfo);
3731 struct AsnDecodeSequenceItem items[] = {
3732 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3733 DistPointName), CRYPT_AsnDecodeDistPointName,
3734 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3735 offsetof(CRL_ISSUING_DIST_POINT,
3736 DistPointName.u.FullName.rgAltEntry), 0 },
3737 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3738 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3740 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3741 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3743 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3744 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3745 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3746 OnlySomeReasonFlags.pbData), 0 },
3747 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3748 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3751 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3752 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3753 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3757 SetLastError(STATUS_ACCESS_VIOLATION);
3764 static BOOL WINAPI CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType,
3765 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3766 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3769 struct AsnDecodeSequenceItem items[] = {
3770 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
3771 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
3773 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
3774 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
3775 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
3777 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3778 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3780 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3781 pDecodePara, pvStructInfo, *pcbStructInfo);
3783 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3784 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3785 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
3786 issuerSerial ? issuerSerial->Issuer.pbData : NULL);
3787 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
3789 SetLastError(CRYPT_E_ASN1_CORRUPT);
3792 TRACE("returning %d\n", ret);
3796 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
3797 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3798 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3802 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3803 pDecodePara, pvStructInfo, *pcbStructInfo);
3807 struct AsnDecodeSequenceItem items[] = {
3808 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
3809 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3810 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
3811 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
3812 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
3813 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
3814 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3815 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
3816 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
3817 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3818 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
3819 HashEncryptionAlgorithm.pszObjId), 0 },
3820 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CMSG_SIGNER_INFO, AuthAttrs),
3821 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3822 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
3823 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
3824 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3825 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
3826 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
3827 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
3828 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
3831 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3832 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3833 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3837 SetLastError(STATUS_ACCESS_VIOLATION);
3840 TRACE("returning %d\n", ret);
3844 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3845 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3846 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3848 static HCRYPTOIDFUNCSET set = NULL;
3850 CryptDecodeObjectExFunc decodeFunc = NULL;
3851 HCRYPTOIDFUNCADDR hFunc = NULL;
3853 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
3854 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
3855 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3857 if (!pvStructInfo && !pcbStructInfo)
3859 SetLastError(ERROR_INVALID_PARAMETER);
3862 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3863 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3865 SetLastError(ERROR_FILE_NOT_FOUND);
3870 SetLastError(CRYPT_E_ASN1_EOD);
3873 if (cbEncoded > MAX_ENCODED_LEN)
3875 SetLastError(CRYPT_E_ASN1_LARGE);
3879 SetLastError(NOERROR);
3880 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3881 *(BYTE **)pvStructInfo = NULL;
3882 if (!HIWORD(lpszStructType))
3884 switch (LOWORD(lpszStructType))
3886 case (WORD)X509_CERT:
3887 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3889 case (WORD)X509_CERT_TO_BE_SIGNED:
3890 decodeFunc = CRYPT_AsnDecodeCert;
3892 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3893 decodeFunc = CRYPT_AsnDecodeCRL;
3895 case (WORD)X509_EXTENSIONS:
3896 decodeFunc = CRYPT_AsnDecodeExtensions;
3898 case (WORD)X509_NAME_VALUE:
3899 decodeFunc = CRYPT_AsnDecodeNameValue;
3901 case (WORD)X509_NAME:
3902 decodeFunc = CRYPT_AsnDecodeName;
3904 case (WORD)X509_PUBLIC_KEY_INFO:
3905 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
3907 case (WORD)X509_AUTHORITY_KEY_ID:
3908 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3910 case (WORD)X509_ALTERNATE_NAME:
3911 decodeFunc = CRYPT_AsnDecodeAltName;
3913 case (WORD)X509_BASIC_CONSTRAINTS:
3914 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3916 case (WORD)X509_BASIC_CONSTRAINTS2:
3917 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3919 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3920 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3922 case (WORD)X509_UNICODE_NAME:
3923 decodeFunc = CRYPT_AsnDecodeUnicodeName;
3925 case (WORD)PKCS_ATTRIBUTE:
3926 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
3928 case (WORD)X509_UNICODE_NAME_VALUE:
3929 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
3931 case (WORD)X509_OCTET_STRING:
3932 decodeFunc = CRYPT_AsnDecodeOctets;
3934 case (WORD)X509_BITS:
3935 case (WORD)X509_KEY_USAGE:
3936 decodeFunc = CRYPT_AsnDecodeBits;
3938 case (WORD)X509_INTEGER:
3939 decodeFunc = CRYPT_AsnDecodeInt;
3941 case (WORD)X509_MULTI_BYTE_INTEGER:
3942 decodeFunc = CRYPT_AsnDecodeInteger;
3944 case (WORD)X509_MULTI_BYTE_UINT:
3945 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3947 case (WORD)X509_ENUMERATED:
3948 decodeFunc = CRYPT_AsnDecodeEnumerated;
3950 case (WORD)X509_CHOICE_OF_TIME:
3951 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3953 case (WORD)X509_AUTHORITY_KEY_ID2:
3954 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
3956 case (WORD)PKCS_CONTENT_INFO:
3957 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
3959 case (WORD)X509_SEQUENCE_OF_ANY:
3960 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3962 case (WORD)PKCS_UTC_TIME:
3963 decodeFunc = CRYPT_AsnDecodeUtcTime;
3965 case (WORD)X509_CRL_DIST_POINTS:
3966 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3968 case (WORD)X509_ENHANCED_KEY_USAGE:
3969 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3971 case (WORD)PKCS_ATTRIBUTES:
3972 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
3974 case (WORD)X509_ISSUING_DIST_POINT:
3975 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3977 case (WORD)PKCS7_SIGNER_INFO:
3978 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
3981 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3984 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3985 decodeFunc = CRYPT_AsnDecodeExtensions;
3986 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3987 decodeFunc = CRYPT_AsnDecodeUtcTime;
3988 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3989 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3990 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3991 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
3992 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3993 decodeFunc = CRYPT_AsnDecodeEnumerated;
3994 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3995 decodeFunc = CRYPT_AsnDecodeBits;
3996 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3997 decodeFunc = CRYPT_AsnDecodeOctets;
3998 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3999 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4000 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4001 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4002 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4003 decodeFunc = CRYPT_AsnDecodeAltName;
4004 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4005 decodeFunc = CRYPT_AsnDecodeAltName;
4006 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4007 decodeFunc = CRYPT_AsnDecodeAltName;
4008 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4009 decodeFunc = CRYPT_AsnDecodeAltName;
4010 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4011 decodeFunc = CRYPT_AsnDecodeAltName;
4012 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4013 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4014 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4015 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4016 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4017 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4019 TRACE("OID %s not found or unimplemented, looking for DLL\n",
4020 debugstr_a(lpszStructType));
4024 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4025 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4026 (void **)&decodeFunc, &hFunc);
4029 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4030 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4032 SetLastError(ERROR_FILE_NOT_FOUND);
4034 CryptFreeOIDFunctionAddress(hFunc, 0);