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
48 #include "wine/debug.h"
49 #include "wine/exception.h"
50 #include "crypt32_private.h"
52 /* This is a bit arbitrary, but to set some limit: */
53 #define MAX_ENCODED_LEN 0x02000000
55 #define ASN_FLAGS_MASK 0xe0
56 #define ASN_TYPE_MASK 0x1f
58 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
66 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
67 DWORD, DWORD, void *, DWORD *);
68 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
69 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
71 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
72 * The dwCertEncodingType and lpszStructType are ignored by the built-in
73 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
74 * since it must call functions in external DLLs that follow these signatures.
76 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
77 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
78 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
79 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
80 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
81 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
82 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
83 * time, doesn't do memory allocation, and doesn't do exception handling.
84 * (This isn't intended to be the externally-called one.)
86 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
87 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
88 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
89 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
90 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
92 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
93 /* Internal function */
94 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
95 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
96 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
97 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
98 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
99 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
100 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
101 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
102 * member has been initialized, doesn't do exception handling, and doesn't do
105 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
106 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
107 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
108 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
109 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
110 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
111 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
112 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
113 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
114 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
115 * member has been initialized, doesn't do exception handling, and doesn't do
116 * memory allocation. Also doesn't check tag, assumes the caller has checked
119 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
120 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
121 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
122 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
123 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
124 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
125 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
126 void *pvStructInfo, DWORD *pcbStructInfo);
128 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
129 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
130 DWORD *pcbStructInfo)
132 static HCRYPTOIDFUNCSET set = NULL;
134 CryptDecodeObjectFunc pCryptDecodeObject;
135 HCRYPTOIDFUNCADDR hFunc;
137 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
138 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
139 pvStructInfo, pcbStructInfo);
141 if (!pvStructInfo && !pcbStructInfo)
143 SetLastError(ERROR_INVALID_PARAMETER);
147 /* Try registered DLL first.. */
149 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
150 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
151 (void **)&pCryptDecodeObject, &hFunc);
152 if (pCryptDecodeObject)
154 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
155 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
156 CryptFreeOIDFunctionAddress(hFunc, 0);
160 /* If not, use CryptDecodeObjectEx */
161 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
162 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
167 /* Gets the number of length bytes from the given (leading) length byte */
168 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
170 /* Helper function to get the encoded length of the data starting at pbEncoded,
171 * where pbEncoded[0] is the tag. If the data are too short to contain a
172 * length or if the length is too large for cbEncoded, sets an appropriate
173 * error code and returns FALSE.
175 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
182 SetLastError(CRYPT_E_ASN1_CORRUPT);
185 else if (pbEncoded[1] <= 0x7f)
187 if (pbEncoded[1] + 1 > cbEncoded)
189 SetLastError(CRYPT_E_ASN1_EOD);
200 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
202 if (lenLen > sizeof(DWORD) + 1)
204 SetLastError(CRYPT_E_ASN1_LARGE);
207 else if (lenLen + 2 > cbEncoded)
209 SetLastError(CRYPT_E_ASN1_CORRUPT);
222 if (out + lenLen + 1 > cbEncoded)
224 SetLastError(CRYPT_E_ASN1_EOD);
237 /* Helper function to check *pcbStructInfo, set it to the required size, and
238 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
239 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
240 * pointer to the newly allocated memory.
242 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
243 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
248 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
250 if (pDecodePara && pDecodePara->pfnAlloc)
251 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
253 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
254 if (!*(BYTE **)pvStructInfo)
257 *pcbStructInfo = bytesNeeded;
259 else if (*pcbStructInfo < bytesNeeded)
261 *pcbStructInfo = bytesNeeded;
262 SetLastError(ERROR_MORE_DATA);
269 * The expected tag of the item. If tag is 0, decodeFunc is called
270 * regardless of the tag value seen.
272 * A sequence is decoded into a struct. The offset member is the
273 * offset of this item within that struct.
275 * The decoder function to use. If this is NULL, then the member isn't
276 * decoded, but minSize space is reserved for it.
278 * The minimum amount of space occupied after decoding. You must set this.
280 * If true, and the tag doesn't match the expected tag for this item,
281 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
282 * filled with 0 for this member.
283 * hasPointer, pointerOffset, minSize:
284 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
285 * the offset within the (outer) struct of the data pointer (or to the
286 * first data pointer, if more than one exist).
288 * Used by CRYPT_AsnDecodeSequence, not for your use.
290 struct AsnDecodeSequenceItem
294 CryptDecodeObjectExFunc decodeFunc;
302 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
303 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
304 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData)
310 ptr = pbEncoded + 1 + GET_LEN_BYTES(pbEncoded[1]);
311 for (i = 0, ret = TRUE; ret && i < cItem; i++)
313 if (cbEncoded - (ptr - pbEncoded) != 0)
317 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
320 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
322 if (ptr[0] == items[i].tag || !items[i].tag)
324 if (nextData && pvStructInfo && items[i].hasPointer)
326 TRACE("Setting next pointer to %p\n",
328 *(BYTE **)((BYTE *)pvStructInfo +
329 items[i].pointerOffset) = nextData;
331 if (items[i].decodeFunc)
334 TRACE("decoding item %d\n", i);
336 TRACE("sizing item %d\n", i);
337 ret = items[i].decodeFunc(dwCertEncodingType,
338 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
339 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
340 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
341 : NULL, &items[i].size);
344 if (nextData && items[i].hasPointer &&
345 items[i].size > items[i].minSize)
347 nextData += items[i].size - items[i].minSize;
348 /* align nextData to DWORD boundaries */
349 if (items[i].size % sizeof(DWORD))
350 nextData += sizeof(DWORD) - items[i].size %
353 /* Account for alignment padding */
354 if (items[i].size % sizeof(DWORD))
355 items[i].size += sizeof(DWORD) -
356 items[i].size % sizeof(DWORD);
357 ptr += 1 + nextItemLenBytes + nextItemLen;
359 else if (items[i].optional &&
360 GetLastError() == CRYPT_E_ASN1_BADTAG)
362 TRACE("skipping optional item %d\n", i);
363 items[i].size = items[i].minSize;
364 SetLastError(NOERROR);
368 TRACE("item %d failed: %08x\n", i,
372 items[i].size = items[i].minSize;
374 else if (items[i].optional)
376 TRACE("skipping optional item %d\n", i);
377 items[i].size = items[i].minSize;
381 TRACE("tag %02x doesn't match expected %02x\n",
382 ptr[0], items[i].tag);
383 SetLastError(CRYPT_E_ASN1_BADTAG);
388 else if (items[i].optional)
390 TRACE("missing optional item %d, skipping\n", i);
391 items[i].size = items[i].minSize;
395 TRACE("not enough bytes for item %d, failing\n", i);
396 SetLastError(CRYPT_E_ASN1_CORRUPT);
400 if (cbEncoded - (ptr - pbEncoded) != 0)
402 TRACE("%d remaining bytes, failing\n", cbEncoded -
404 SetLastError(CRYPT_E_ASN1_CORRUPT);
410 /* This decodes an arbitrary sequence into a contiguous block of memory
411 * (basically, a struct.) Each element being decoded is described by a struct
412 * AsnDecodeSequenceItem, see above.
413 * startingPointer is an optional pointer to the first place where dynamic
414 * data will be stored. If you know the starting offset, you may pass it
415 * here. Otherwise, pass NULL, and one will be inferred from the items.
416 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
417 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
419 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
420 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
421 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
422 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
426 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
427 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
430 if (pbEncoded[0] == ASN_SEQUENCE)
434 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
438 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
439 cbEncoded, dwFlags, NULL, NULL);
442 DWORD bytesNeeded = 0, structSize = 0;
444 for (i = 0; i < cItem; i++)
446 bytesNeeded += items[i].size;
447 structSize += items[i].minSize;
450 *pcbStructInfo = bytesNeeded;
451 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
452 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
456 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
457 pvStructInfo = *(BYTE **)pvStructInfo;
459 nextData = (BYTE *)startingPointer;
461 nextData = (BYTE *)pvStructInfo + structSize;
462 memset(pvStructInfo, 0, structSize);
463 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
464 pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
471 SetLastError(CRYPT_E_ASN1_BADTAG);
474 TRACE("returning %d (%08x)\n", ret, GetLastError());
479 * The expected tag of the entire encoded array (usually a variant
480 * of ASN_SETOF or ASN_SEQUENCEOF.)
482 * used to decode each item in the array
484 * is the minimum size of each decoded item
486 * indicates whether each item has a dynamic pointer
488 * indicates the offset within itemSize at which the pointer exists
490 struct AsnArrayDescriptor
493 CryptDecodeObjectExFunc decodeFunc;
499 struct AsnArrayItemSize
505 /* Decodes an array of like types into a struct GenericArray.
506 * The layout and decoding of the array are described by a struct
507 * AsnArrayDescriptor.
509 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
510 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
511 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
512 void *startingPointer)
516 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
517 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
520 if (pbEncoded[0] == arrayDesc->tag)
524 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
526 DWORD bytesNeeded, cItems = 0;
527 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
528 /* There can be arbitrarily many items, but there is often only one.
530 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
532 bytesNeeded = sizeof(struct GenericArray);
537 for (ptr = pbEncoded + 1 + lenBytes; ret &&
538 ptr - pbEncoded - 1 - lenBytes < dataLen; )
540 DWORD itemLenBytes, itemDataLen, size;
542 itemLenBytes = GET_LEN_BYTES(ptr[1]);
543 /* Each item decoded may not tolerate extraneous bytes, so
544 * get the length of the next element and pass it directly.
546 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
549 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
550 1 + itemLenBytes + itemDataLen,
551 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
558 if (itemSizes != &itemSize)
559 itemSizes = CryptMemRealloc(itemSizes,
560 cItems * sizeof(struct AsnArrayItemSize));
565 cItems * sizeof(struct AsnArrayItemSize));
567 memcpy(itemSizes, &itemSize, sizeof(itemSize));
571 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
573 itemSizes[cItems - 1].size = size;
575 ret = CRYPT_GetLen(ptr,
576 cbEncoded - (ptr - pbEncoded), &nextLen);
578 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
588 *pcbStructInfo = bytesNeeded;
589 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
590 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
595 struct GenericArray *array;
597 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
598 pvStructInfo = *(BYTE **)pvStructInfo;
599 array = (struct GenericArray *)pvStructInfo;
600 array->cItems = cItems;
602 array->rgItems = startingPointer;
604 array->rgItems = (BYTE *)array +
605 sizeof(struct GenericArray);
606 nextData = (BYTE *)array->rgItems +
607 array->cItems * arrayDesc->itemSize;
608 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
609 i < cItems && ptr - pbEncoded - 1 - lenBytes <
612 if (arrayDesc->hasPointer)
613 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
614 + arrayDesc->pointerOffset) = nextData;
615 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
616 itemSizes[i].encodedLen,
617 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
618 array->rgItems + i * arrayDesc->itemSize,
624 nextData += itemSizes[i].size - arrayDesc->itemSize;
625 ret = CRYPT_GetLen(ptr,
626 cbEncoded - (ptr - pbEncoded), &nextLen);
628 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
633 if (itemSizes != &itemSize)
634 CryptMemFree(itemSizes);
639 SetLastError(CRYPT_E_ASN1_BADTAG);
645 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
646 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
647 * to CRYPT_E_ASN1_CORRUPT.
648 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
651 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
652 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
653 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
658 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
660 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
661 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
663 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
664 bytesNeeded += 1 + lenBytes + dataLen;
667 *pcbStructInfo = bytesNeeded;
668 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
669 pvStructInfo, pcbStructInfo, bytesNeeded)))
671 CRYPT_DER_BLOB *blob;
673 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
674 pvStructInfo = *(BYTE **)pvStructInfo;
675 blob = (CRYPT_DER_BLOB *)pvStructInfo;
676 blob->cbData = 1 + lenBytes + dataLen;
679 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
680 blob->pbData = (BYTE *)pbEncoded;
683 assert(blob->pbData);
684 memcpy(blob->pbData, pbEncoded, blob->cbData);
689 SetLastError(CRYPT_E_ASN1_CORRUPT);
697 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
698 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
699 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
700 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
704 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
705 pDecodePara, pvStructInfo, *pcbStructInfo);
707 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
710 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
711 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
712 pvStructInfo, pcbStructInfo);
713 if (ret && pvStructInfo)
715 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
722 for (i = 0; i < blob->cbData / 2; i++)
724 temp = blob->pbData[i];
725 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
726 blob->pbData[blob->cbData - i - 1] = temp;
730 TRACE("returning %d (%08x)\n", ret, GetLastError());
734 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
735 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
736 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
740 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
741 pDecodePara, pvStructInfo, *pcbStructInfo);
745 struct AsnDecodeSequenceItem items[] = {
746 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
747 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
748 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
749 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
750 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
751 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
752 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
753 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
754 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
755 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
758 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
759 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
760 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
761 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
762 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
766 SetLastError(STATUS_ACCESS_VIOLATION);
771 TRACE("Returning %d (%08x)\n", ret, GetLastError());
775 /* Internal function */
776 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
777 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
778 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
783 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
785 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
787 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
788 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
789 pvStructInfo, pcbStructInfo);
794 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
795 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
796 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
800 struct AsnDecodeSequenceItem items[] = {
801 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
802 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
803 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
804 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
807 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
808 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
809 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
813 /* Internal function */
814 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
815 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
816 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
821 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
823 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
825 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
826 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
827 pDecodePara, pvStructInfo, pcbStructInfo);
832 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
833 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
834 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
837 struct AsnDecodeSequenceItem items[] = {
838 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
839 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
840 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
841 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
842 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
843 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
844 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
845 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
846 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
847 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
849 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
850 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
852 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
853 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
855 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
856 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
857 FALSE, TRUE, offsetof(CERT_INFO,
858 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
859 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
860 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
861 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
862 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
863 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
864 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
865 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
866 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
867 offsetof(CERT_INFO, rgExtension), 0 },
870 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
871 pDecodePara, pvStructInfo, *pcbStructInfo);
873 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
874 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
875 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
877 TRACE("Returning %d (%08x)\n", ret, GetLastError());
881 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
882 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
883 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
887 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
888 pDecodePara, pvStructInfo, *pcbStructInfo);
892 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
895 /* First try to decode it as a signed cert. */
896 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
897 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
898 (BYTE *)&signedCert, &size);
902 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
903 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
904 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
906 LocalFree(signedCert);
908 /* Failing that, try it as an unsigned cert */
912 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
913 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
914 pDecodePara, pvStructInfo, pcbStructInfo);
919 SetLastError(STATUS_ACCESS_VIOLATION);
924 TRACE("Returning %d (%08x)\n", ret, GetLastError());
928 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
929 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
930 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
933 struct AsnDecodeSequenceItem items[] = {
934 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
935 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
936 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
937 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
938 sizeof(FILETIME), FALSE, FALSE, 0 },
939 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
940 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
941 offsetof(CRL_ENTRY, rgExtension), 0 },
943 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
945 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
948 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
949 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
950 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
954 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
955 * been set prior to calling.
957 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
958 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
959 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
962 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
963 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
964 offsetof(CRL_ENTRY, SerialNumber.pbData) };
965 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
967 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
968 pDecodePara, pvStructInfo, *pcbStructInfo);
970 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
971 pDecodePara, pvStructInfo, pcbStructInfo,
972 entries ? entries->rgItems : NULL);
973 TRACE("Returning %d (%08x)\n", ret, GetLastError());
977 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
978 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
979 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
981 struct AsnDecodeSequenceItem items[] = {
982 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
983 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
984 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
985 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
986 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
987 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
988 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
990 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
991 sizeof(FILETIME), FALSE, FALSE, 0 },
992 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
993 sizeof(FILETIME), TRUE, FALSE, 0 },
994 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
995 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
996 offsetof(CRL_INFO, rgCRLEntry), 0 },
997 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
998 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
999 offsetof(CRL_INFO, rgExtension), 0 },
1003 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1004 pDecodePara, pvStructInfo, *pcbStructInfo);
1006 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1007 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1008 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1010 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1014 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1015 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1016 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1020 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1021 pDecodePara, pvStructInfo, *pcbStructInfo);
1025 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1028 /* First try to decode it as a signed crl. */
1029 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1030 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1031 (BYTE *)&signedCrl, &size);
1035 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1036 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1037 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1038 pvStructInfo, pcbStructInfo);
1039 LocalFree(signedCrl);
1041 /* Failing that, try it as an unsigned crl */
1045 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1046 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1047 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1052 SetLastError(STATUS_ACCESS_VIOLATION);
1057 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1061 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1062 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1063 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1067 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1068 pDecodePara, pvStructInfo, *pcbStructInfo);
1070 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1074 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1076 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1077 DWORD bytesNeeded = sizeof(LPSTR);
1081 /* The largest possible string for the first two components
1082 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1087 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1088 pbEncoded[1 + lenBytes] / 40,
1089 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1091 bytesNeeded += strlen(firstTwo) + 1;
1092 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1093 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1095 /* large enough for ".4000000" */
1099 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1106 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1109 SetLastError(CRYPT_E_ASN1_CORRUPT);
1116 snprintf(str, sizeof(str), ".%d", val);
1117 bytesNeeded += strlen(str);
1122 *pcbStructInfo = bytesNeeded;
1123 else if (*pcbStructInfo < bytesNeeded)
1125 *pcbStructInfo = bytesNeeded;
1126 SetLastError(ERROR_MORE_DATA);
1134 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1137 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1138 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1140 pszObjId += strlen(pszObjId);
1141 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1142 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1146 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1155 sprintf(pszObjId, ".%d", val);
1156 pszObjId += strlen(pszObjId);
1160 *(LPSTR *)pvStructInfo = NULL;
1161 *pcbStructInfo = bytesNeeded;
1168 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1171 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1172 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1173 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1175 struct AsnDecodeSequenceItem items[] = {
1176 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1177 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1178 offsetof(CERT_EXTENSION, pszObjId), 0 },
1179 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1180 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1181 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1182 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1183 offsetof(CERT_EXTENSION, Value.pbData) },
1186 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1188 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1192 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1193 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1194 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1195 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1197 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1198 debugstr_a(ext->pszObjId));
1199 TRACE("returning %d (%08x)\n", ret, GetLastError());
1203 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1204 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1205 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1208 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1209 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1210 offsetof(CERT_EXTENSION, pszObjId) };
1211 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1213 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1214 pDecodePara, pvStructInfo, *pcbStructInfo);
1216 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1217 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1221 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1222 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1223 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1229 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1230 lpszStructType, pbEncoded, cbEncoded,
1231 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1232 if (ret && pvStructInfo)
1234 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1235 pcbStructInfo, *pcbStructInfo);
1238 CERT_EXTENSIONS *exts;
1240 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1241 pvStructInfo = *(BYTE **)pvStructInfo;
1242 exts = (CERT_EXTENSIONS *)pvStructInfo;
1243 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1244 sizeof(CERT_EXTENSIONS));
1245 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1246 lpszStructType, pbEncoded, cbEncoded,
1247 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1254 SetLastError(STATUS_ACCESS_VIOLATION);
1261 /* Warning: this assumes the address of value->Value.pbData is already set, in
1262 * order to avoid overwriting memory. (In some cases, it may change it, if it
1263 * doesn't copy anything to memory.) Be sure to set it correctly!
1265 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1266 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1267 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1271 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1273 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1275 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1276 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1278 switch (pbEncoded[0])
1280 case ASN_OCTETSTRING:
1281 valueType = CERT_RDN_OCTET_STRING;
1282 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1283 bytesNeeded += dataLen;
1285 case ASN_NUMERICSTRING:
1286 valueType = CERT_RDN_NUMERIC_STRING;
1287 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1288 bytesNeeded += dataLen;
1290 case ASN_PRINTABLESTRING:
1291 valueType = CERT_RDN_PRINTABLE_STRING;
1292 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1293 bytesNeeded += dataLen;
1296 valueType = CERT_RDN_IA5_STRING;
1297 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1298 bytesNeeded += dataLen;
1301 valueType = CERT_RDN_T61_STRING;
1302 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1303 bytesNeeded += dataLen;
1305 case ASN_VIDEOTEXSTRING:
1306 valueType = CERT_RDN_VIDEOTEX_STRING;
1307 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1308 bytesNeeded += dataLen;
1310 case ASN_GRAPHICSTRING:
1311 valueType = CERT_RDN_GRAPHIC_STRING;
1312 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1313 bytesNeeded += dataLen;
1315 case ASN_VISIBLESTRING:
1316 valueType = CERT_RDN_VISIBLE_STRING;
1317 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1318 bytesNeeded += dataLen;
1320 case ASN_GENERALSTRING:
1321 valueType = CERT_RDN_GENERAL_STRING;
1322 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1323 bytesNeeded += dataLen;
1325 case ASN_UNIVERSALSTRING:
1326 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1327 SetLastError(CRYPT_E_ASN1_BADTAG);
1330 valueType = CERT_RDN_BMP_STRING;
1331 bytesNeeded += dataLen;
1333 case ASN_UTF8STRING:
1334 valueType = CERT_RDN_UTF8_STRING;
1335 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1336 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1339 SetLastError(CRYPT_E_ASN1_BADTAG);
1344 *pcbStructInfo = bytesNeeded;
1345 else if (*pcbStructInfo < bytesNeeded)
1347 *pcbStructInfo = bytesNeeded;
1348 SetLastError(ERROR_MORE_DATA);
1353 *pcbStructInfo = bytesNeeded;
1354 value->dwValueType = valueType;
1359 assert(value->Value.pbData);
1360 switch (pbEncoded[0])
1362 case ASN_OCTETSTRING:
1363 case ASN_NUMERICSTRING:
1364 case ASN_PRINTABLESTRING:
1367 case ASN_VIDEOTEXSTRING:
1368 case ASN_GRAPHICSTRING:
1369 case ASN_VISIBLESTRING:
1370 case ASN_GENERALSTRING:
1371 value->Value.cbData = dataLen;
1374 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1375 memcpy(value->Value.pbData,
1376 pbEncoded + 1 + lenBytes, dataLen);
1378 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1384 LPWSTR str = (LPWSTR)value->Value.pbData;
1386 value->Value.cbData = dataLen;
1387 for (i = 0; i < dataLen / 2; i++)
1388 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1389 pbEncoded[1 + lenBytes + 2 * i + 1];
1392 case ASN_UTF8STRING:
1394 LPWSTR str = (LPWSTR)value->Value.pbData;
1396 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1397 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1398 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1405 value->Value.cbData = 0;
1406 value->Value.pbData = NULL;
1413 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1414 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1415 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1421 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1422 lpszStructType, pbEncoded, cbEncoded,
1423 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1424 if (ret && pvStructInfo)
1426 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1427 pcbStructInfo, *pcbStructInfo);
1430 CERT_NAME_VALUE *value;
1432 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1433 pvStructInfo = *(BYTE **)pvStructInfo;
1434 value = (CERT_NAME_VALUE *)pvStructInfo;
1435 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1436 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1437 lpszStructType, pbEncoded, cbEncoded,
1438 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1445 SetLastError(STATUS_ACCESS_VIOLATION);
1452 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1453 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1454 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1455 void *pvStructInfo, DWORD *pcbStructInfo)
1459 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1461 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1463 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1464 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1466 switch (pbEncoded[0])
1468 case ASN_NUMERICSTRING:
1469 valueType = CERT_RDN_NUMERIC_STRING;
1470 bytesNeeded += dataLen * 2;
1472 case ASN_PRINTABLESTRING:
1473 valueType = CERT_RDN_PRINTABLE_STRING;
1474 bytesNeeded += dataLen * 2;
1477 valueType = CERT_RDN_IA5_STRING;
1478 bytesNeeded += dataLen * 2;
1481 valueType = CERT_RDN_T61_STRING;
1482 bytesNeeded += dataLen * 2;
1484 case ASN_VIDEOTEXSTRING:
1485 valueType = CERT_RDN_VIDEOTEX_STRING;
1486 bytesNeeded += dataLen * 2;
1488 case ASN_GRAPHICSTRING:
1489 valueType = CERT_RDN_GRAPHIC_STRING;
1490 bytesNeeded += dataLen * 2;
1492 case ASN_VISIBLESTRING:
1493 valueType = CERT_RDN_VISIBLE_STRING;
1494 bytesNeeded += dataLen * 2;
1496 case ASN_GENERALSTRING:
1497 valueType = CERT_RDN_GENERAL_STRING;
1498 bytesNeeded += dataLen * 2;
1500 case ASN_UNIVERSALSTRING:
1501 valueType = CERT_RDN_UNIVERSAL_STRING;
1502 bytesNeeded += dataLen / 2;
1505 valueType = CERT_RDN_BMP_STRING;
1506 bytesNeeded += dataLen;
1508 case ASN_UTF8STRING:
1509 valueType = CERT_RDN_UTF8_STRING;
1510 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1511 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1514 SetLastError(CRYPT_E_ASN1_BADTAG);
1519 *pcbStructInfo = bytesNeeded;
1520 else if (*pcbStructInfo < bytesNeeded)
1522 *pcbStructInfo = bytesNeeded;
1523 SetLastError(ERROR_MORE_DATA);
1528 *pcbStructInfo = bytesNeeded;
1529 value->dwValueType = valueType;
1533 LPWSTR str = (LPWSTR)value->Value.pbData;
1535 assert(value->Value.pbData);
1536 switch (pbEncoded[0])
1538 case ASN_NUMERICSTRING:
1539 case ASN_PRINTABLESTRING:
1542 case ASN_VIDEOTEXSTRING:
1543 case ASN_GRAPHICSTRING:
1544 case ASN_VISIBLESTRING:
1545 case ASN_GENERALSTRING:
1546 value->Value.cbData = dataLen * 2;
1547 for (i = 0; i < dataLen; i++)
1548 str[i] = pbEncoded[1 + lenBytes + i];
1550 case ASN_UNIVERSALSTRING:
1551 value->Value.cbData = dataLen / 2;
1552 for (i = 0; i < dataLen / 4; i++)
1553 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1554 | pbEncoded[1 + lenBytes + 2 * i + 3];
1557 value->Value.cbData = dataLen;
1558 for (i = 0; i < dataLen / 2; i++)
1559 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1560 pbEncoded[1 + lenBytes + 2 * i + 1];
1562 case ASN_UTF8STRING:
1563 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1564 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1565 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1571 value->Value.cbData = 0;
1572 value->Value.pbData = NULL;
1579 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1580 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1581 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1587 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1588 lpszStructType, pbEncoded, cbEncoded,
1589 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1590 if (ret && pvStructInfo)
1592 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1593 pcbStructInfo, *pcbStructInfo);
1596 CERT_NAME_VALUE *value;
1598 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1599 pvStructInfo = *(BYTE **)pvStructInfo;
1600 value = (CERT_NAME_VALUE *)pvStructInfo;
1601 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1602 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1603 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1604 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1611 SetLastError(STATUS_ACCESS_VIOLATION);
1618 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1619 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1620 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1623 struct AsnDecodeSequenceItem items[] = {
1624 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1625 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1626 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1627 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1628 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1629 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1631 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1633 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1634 pvStructInfo, *pcbStructInfo);
1637 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1638 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1639 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1640 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1643 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1644 debugstr_a(attr->pszObjId));
1645 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1647 TRACE("returning %d (%08x)\n", ret, GetLastError());
1651 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1652 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1653 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1656 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1657 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1658 offsetof(CERT_RDN_ATTR, pszObjId) };
1659 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1661 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1662 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1666 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1667 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1668 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1674 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1675 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1676 offsetof(CERT_RDN, rgRDNAttr) };
1678 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1679 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1683 SetLastError(STATUS_ACCESS_VIOLATION);
1690 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
1691 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1692 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1695 struct AsnDecodeSequenceItem items[] = {
1696 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1697 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1698 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1699 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1700 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1701 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1703 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1705 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1706 pvStructInfo, *pcbStructInfo);
1709 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1710 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1711 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1712 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1715 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1716 debugstr_a(attr->pszObjId));
1717 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1719 TRACE("returning %d (%08x)\n", ret, GetLastError());
1723 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
1724 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1725 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1728 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1729 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1730 offsetof(CERT_RDN_ATTR, pszObjId) };
1731 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1733 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1734 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1738 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1739 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1740 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1746 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1747 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1748 offsetof(CERT_RDN, rgRDNAttr) };
1750 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1751 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1755 SetLastError(STATUS_ACCESS_VIOLATION);
1762 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1763 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1764 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1767 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1769 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1770 pDecodePara, pvStructInfo, *pcbStructInfo);
1772 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1773 bytesNeeded += cbEncoded;
1775 *pcbStructInfo = bytesNeeded;
1776 else if (*pcbStructInfo < bytesNeeded)
1778 SetLastError(ERROR_MORE_DATA);
1779 *pcbStructInfo = bytesNeeded;
1784 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1786 *pcbStructInfo = bytesNeeded;
1787 blob->cbData = cbEncoded;
1788 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1789 blob->pbData = (LPBYTE)pbEncoded;
1792 assert(blob->pbData);
1793 memcpy(blob->pbData, pbEncoded, blob->cbData);
1799 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1800 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1801 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1803 CRYPT_ALGORITHM_IDENTIFIER *algo =
1804 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1806 struct AsnDecodeSequenceItem items[] = {
1807 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1808 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1809 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1810 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1811 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1812 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1815 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1816 pDecodePara, pvStructInfo, *pcbStructInfo);
1818 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1819 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1820 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1821 if (ret && pvStructInfo)
1823 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1824 debugstr_a(algo->pszObjId));
1829 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1830 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1831 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1834 struct AsnDecodeSequenceItem items[] = {
1835 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1836 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1837 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1838 Algorithm.pszObjId) },
1839 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1840 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1841 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1843 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1845 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1846 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1847 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1848 info->Algorithm.Parameters.pbData : NULL);
1852 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1853 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1854 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1862 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1863 lpszStructType, pbEncoded, cbEncoded,
1864 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1867 *pcbStructInfo = bytesNeeded;
1868 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1869 pvStructInfo, pcbStructInfo, bytesNeeded)))
1871 PCERT_PUBLIC_KEY_INFO info;
1873 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1874 pvStructInfo = *(BYTE **)pvStructInfo;
1875 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1876 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
1877 sizeof(CERT_PUBLIC_KEY_INFO);
1878 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1879 lpszStructType, pbEncoded, cbEncoded,
1880 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1887 SetLastError(STATUS_ACCESS_VIOLATION);
1894 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
1895 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1896 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1902 SetLastError(CRYPT_E_ASN1_CORRUPT);
1905 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
1907 SetLastError(CRYPT_E_ASN1_CORRUPT);
1910 if (pbEncoded[1] > 1)
1912 SetLastError(CRYPT_E_ASN1_CORRUPT);
1917 *pcbStructInfo = sizeof(BOOL);
1920 else if (*pcbStructInfo < sizeof(BOOL))
1922 *pcbStructInfo = sizeof(BOOL);
1923 SetLastError(ERROR_MORE_DATA);
1928 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
1931 TRACE("returning %d (%08x)\n", ret, GetLastError());
1935 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
1936 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1937 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1939 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
1940 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
1943 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1944 pDecodePara, pvStructInfo, *pcbStructInfo);
1948 SetLastError(CRYPT_E_ASN1_CORRUPT);
1951 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
1953 SetLastError(CRYPT_E_ASN1_BADTAG);
1956 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1957 if (1 + lenBytes > cbEncoded)
1959 SetLastError(CRYPT_E_ASN1_CORRUPT);
1962 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1964 switch (pbEncoded[0] & ASN_TYPE_MASK)
1966 case 1: /* rfc822Name */
1967 case 2: /* dNSName */
1968 case 6: /* uniformResourceIdentifier */
1969 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1971 case 7: /* iPAddress */
1972 bytesNeeded += dataLen;
1974 case 8: /* registeredID */
1975 /* FIXME: decode as OID */
1976 case 0: /* otherName */
1977 case 4: /* directoryName */
1979 SetLastError(CRYPT_E_ASN1_BADTAG);
1982 case 3: /* x400Address, unimplemented */
1983 case 5: /* ediPartyName, unimplemented */
1984 SetLastError(CRYPT_E_ASN1_BADTAG);
1988 SetLastError(CRYPT_E_ASN1_CORRUPT);
1994 *pcbStructInfo = bytesNeeded;
1995 else if (*pcbStructInfo < bytesNeeded)
1997 *pcbStructInfo = bytesNeeded;
1998 SetLastError(ERROR_MORE_DATA);
2003 *pcbStructInfo = bytesNeeded;
2004 /* MS used values one greater than the asn1 ones.. sigh */
2005 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2006 switch (pbEncoded[0] & ASN_TYPE_MASK)
2008 case 1: /* rfc822Name */
2009 case 2: /* dNSName */
2010 case 6: /* uniformResourceIdentifier */
2014 for (i = 0; i < dataLen; i++)
2015 entry->u.pwszURL[i] =
2016 (WCHAR)pbEncoded[1 + lenBytes + i];
2017 entry->u.pwszURL[i] = 0;
2018 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2019 debugstr_w(entry->u.pwszURL));
2022 case 7: /* iPAddress */
2023 /* The next data pointer is in the pwszURL spot, that is,
2024 * the first 4 bytes. Need to move it to the next spot.
2026 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2027 entry->u.IPAddress.cbData = dataLen;
2028 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2038 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2039 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2040 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2043 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2044 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2045 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2046 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2048 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2049 pDecodePara, pvStructInfo, *pcbStructInfo);
2052 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2053 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2054 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2058 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2059 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2060 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2066 struct AsnDecodeSequenceItem items[] = {
2067 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2068 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2069 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2070 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2071 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2072 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2073 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2074 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2075 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2076 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2077 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2080 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2081 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2082 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2086 SetLastError(STATUS_ACCESS_VIOLATION);
2093 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2094 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2095 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2099 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2100 pDecodePara, pvStructInfo, *pcbStructInfo);
2104 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2105 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2106 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2108 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2109 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2113 SetLastError(STATUS_ACCESS_VIOLATION);
2120 struct PATH_LEN_CONSTRAINT
2122 BOOL fPathLenConstraint;
2123 DWORD dwPathLenConstraint;
2126 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2127 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2128 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2132 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2133 pvStructInfo, *pcbStructInfo);
2137 if (pbEncoded[0] == ASN_INTEGER)
2139 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2142 *pcbStructInfo = bytesNeeded;
2143 else if (*pcbStructInfo < bytesNeeded)
2145 SetLastError(ERROR_MORE_DATA);
2146 *pcbStructInfo = bytesNeeded;
2151 struct PATH_LEN_CONSTRAINT *constraint =
2152 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2153 DWORD size = sizeof(constraint->dwPathLenConstraint);
2155 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2156 pbEncoded, cbEncoded, 0, NULL,
2157 &constraint->dwPathLenConstraint, &size);
2159 constraint->fPathLenConstraint = TRUE;
2160 TRACE("got an int, dwPathLenConstraint is %d\n",
2161 constraint->dwPathLenConstraint);
2166 SetLastError(CRYPT_E_ASN1_CORRUPT);
2170 TRACE("returning %d (%08x)\n", ret, GetLastError());
2174 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2175 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2176 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2179 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2180 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2181 offsetof(CERT_NAME_BLOB, pbData) };
2182 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2184 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2185 pDecodePara, pvStructInfo, *pcbStructInfo);
2187 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2188 pDecodePara, pvStructInfo, pcbStructInfo,
2189 entries ? entries->rgItems : NULL);
2190 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2194 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2195 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2196 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2202 struct AsnDecodeSequenceItem items[] = {
2203 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2204 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2205 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2206 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2207 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2208 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2209 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2210 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2211 sizeof(struct GenericArray), TRUE, TRUE,
2212 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2215 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2216 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2217 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2221 SetLastError(STATUS_ACCESS_VIOLATION);
2228 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2229 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2230 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2236 struct AsnDecodeSequenceItem items[] = {
2237 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2238 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2239 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2240 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2241 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2244 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2245 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2246 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2250 SetLastError(STATUS_ACCESS_VIOLATION);
2257 #define RSA1_MAGIC 0x31415352
2259 struct DECODED_RSA_PUB_KEY
2262 CRYPT_INTEGER_BLOB modulus;
2265 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2266 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2267 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2273 struct AsnDecodeSequenceItem items[] = {
2274 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2275 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2276 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2278 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2279 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2281 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2284 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2285 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2286 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2289 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2290 decodedKey->modulus.cbData;
2294 *pcbStructInfo = bytesNeeded;
2297 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2298 pvStructInfo, pcbStructInfo, bytesNeeded)))
2301 RSAPUBKEY *rsaPubKey;
2303 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2304 pvStructInfo = *(BYTE **)pvStructInfo;
2305 hdr = (BLOBHEADER *)pvStructInfo;
2306 hdr->bType = PUBLICKEYBLOB;
2307 hdr->bVersion = CUR_BLOB_VERSION;
2309 hdr->aiKeyAlg = CALG_RSA_KEYX;
2310 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2311 sizeof(BLOBHEADER));
2312 rsaPubKey->magic = RSA1_MAGIC;
2313 rsaPubKey->pubexp = decodedKey->pubexp;
2314 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2315 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2316 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2317 decodedKey->modulus.cbData);
2319 LocalFree(decodedKey);
2324 SetLastError(STATUS_ACCESS_VIOLATION);
2331 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2332 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2333 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2336 DWORD bytesNeeded, dataLen;
2338 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2339 pDecodePara, pvStructInfo, *pcbStructInfo);
2341 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2343 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2344 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2346 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2348 *pcbStructInfo = bytesNeeded;
2349 else if (*pcbStructInfo < bytesNeeded)
2351 SetLastError(ERROR_MORE_DATA);
2352 *pcbStructInfo = bytesNeeded;
2357 CRYPT_DATA_BLOB *blob;
2358 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2360 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2361 blob->cbData = dataLen;
2362 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2363 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2366 assert(blob->pbData);
2368 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2376 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2377 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2378 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2382 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2383 pDecodePara, pvStructInfo, *pcbStructInfo);
2391 SetLastError(CRYPT_E_ASN1_CORRUPT);
2394 else if (pbEncoded[0] != ASN_OCTETSTRING)
2396 SetLastError(CRYPT_E_ASN1_BADTAG);
2399 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2400 lpszStructType, pbEncoded, cbEncoded,
2401 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2404 *pcbStructInfo = bytesNeeded;
2405 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2406 pvStructInfo, pcbStructInfo, bytesNeeded)))
2408 CRYPT_DATA_BLOB *blob;
2410 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2411 pvStructInfo = *(BYTE **)pvStructInfo;
2412 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2413 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2414 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2415 lpszStructType, pbEncoded, cbEncoded,
2416 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2423 SetLastError(STATUS_ACCESS_VIOLATION);
2430 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2431 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2432 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2436 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2437 pDecodePara, pvStructInfo, *pcbStructInfo);
2439 if (pbEncoded[0] == ASN_BITSTRING)
2441 DWORD bytesNeeded, dataLen;
2443 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2445 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2446 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2448 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2450 *pcbStructInfo = bytesNeeded;
2451 else if (*pcbStructInfo < bytesNeeded)
2453 *pcbStructInfo = bytesNeeded;
2454 SetLastError(ERROR_MORE_DATA);
2459 CRYPT_BIT_BLOB *blob;
2461 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2462 blob->cbData = dataLen - 1;
2463 blob->cUnusedBits = *(pbEncoded + 1 +
2464 GET_LEN_BYTES(pbEncoded[1]));
2465 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2467 blob->pbData = (BYTE *)pbEncoded + 2 +
2468 GET_LEN_BYTES(pbEncoded[1]);
2472 assert(blob->pbData);
2475 BYTE mask = 0xff << blob->cUnusedBits;
2477 memcpy(blob->pbData, pbEncoded + 2 +
2478 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2479 blob->pbData[blob->cbData - 1] &= mask;
2487 SetLastError(CRYPT_E_ASN1_BADTAG);
2490 TRACE("returning %d (%08x)\n", ret, GetLastError());
2494 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2495 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2496 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2500 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2501 pDecodePara, pvStructInfo, pcbStructInfo);
2507 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2508 lpszStructType, pbEncoded, cbEncoded,
2509 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2512 *pcbStructInfo = bytesNeeded;
2513 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2514 pvStructInfo, pcbStructInfo, bytesNeeded)))
2516 CRYPT_BIT_BLOB *blob;
2518 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2519 pvStructInfo = *(BYTE **)pvStructInfo;
2520 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2521 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2522 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2523 lpszStructType, pbEncoded, cbEncoded,
2524 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2531 SetLastError(STATUS_ACCESS_VIOLATION);
2535 TRACE("returning %d (%08x)\n", ret, GetLastError());
2539 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2540 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2541 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2547 *pcbStructInfo = sizeof(int);
2552 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2553 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2554 DWORD size = sizeof(buf);
2556 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2557 if (pbEncoded[0] != ASN_INTEGER)
2559 SetLastError(CRYPT_E_ASN1_BADTAG);
2563 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2564 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
2568 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2569 pvStructInfo, pcbStructInfo, sizeof(int))))
2573 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2574 pvStructInfo = *(BYTE **)pvStructInfo;
2575 if (blob->pbData[blob->cbData - 1] & 0x80)
2577 /* initialize to a negative value to sign-extend */
2582 for (i = 0; i < blob->cbData; i++)
2585 val |= blob->pbData[blob->cbData - i - 1];
2587 memcpy(pvStructInfo, &val, sizeof(int));
2590 else if (GetLastError() == ERROR_MORE_DATA)
2591 SetLastError(CRYPT_E_ASN1_LARGE);
2595 SetLastError(STATUS_ACCESS_VIOLATION);
2602 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2603 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2604 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2607 DWORD bytesNeeded, dataLen;
2609 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2611 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2613 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2615 *pcbStructInfo = bytesNeeded;
2616 else if (*pcbStructInfo < bytesNeeded)
2618 *pcbStructInfo = bytesNeeded;
2619 SetLastError(ERROR_MORE_DATA);
2624 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2626 blob->cbData = dataLen;
2627 assert(blob->pbData);
2632 for (i = 0; i < blob->cbData; i++)
2634 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2643 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2644 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2645 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2653 if (pbEncoded[0] != ASN_INTEGER)
2655 SetLastError(CRYPT_E_ASN1_BADTAG);
2659 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2660 lpszStructType, pbEncoded, cbEncoded,
2661 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
2665 *pcbStructInfo = bytesNeeded;
2666 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2667 pvStructInfo, pcbStructInfo, bytesNeeded)))
2669 CRYPT_INTEGER_BLOB *blob;
2671 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2672 pvStructInfo = *(BYTE **)pvStructInfo;
2673 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2674 blob->pbData = (BYTE *)pvStructInfo +
2675 sizeof(CRYPT_INTEGER_BLOB);
2676 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2677 lpszStructType, pbEncoded, cbEncoded,
2678 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2685 SetLastError(STATUS_ACCESS_VIOLATION);
2692 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
2693 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2694 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2695 void *pvStructInfo, DWORD *pcbStructInfo)
2699 if (pbEncoded[0] == ASN_INTEGER)
2701 DWORD bytesNeeded, dataLen;
2703 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2705 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2707 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2709 *pcbStructInfo = bytesNeeded;
2710 else if (*pcbStructInfo < bytesNeeded)
2712 *pcbStructInfo = bytesNeeded;
2713 SetLastError(ERROR_MORE_DATA);
2718 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2720 blob->cbData = dataLen;
2721 assert(blob->pbData);
2722 /* remove leading zero byte if it exists */
2723 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2732 for (i = 0; i < blob->cbData; i++)
2734 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2743 SetLastError(CRYPT_E_ASN1_BADTAG);
2749 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2750 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2751 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2759 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2760 lpszStructType, pbEncoded, cbEncoded,
2761 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2764 *pcbStructInfo = bytesNeeded;
2765 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2766 pvStructInfo, pcbStructInfo, bytesNeeded)))
2768 CRYPT_INTEGER_BLOB *blob;
2770 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2771 pvStructInfo = *(BYTE **)pvStructInfo;
2772 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2773 blob->pbData = (BYTE *)pvStructInfo +
2774 sizeof(CRYPT_INTEGER_BLOB);
2775 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2776 lpszStructType, pbEncoded, cbEncoded,
2777 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2784 SetLastError(STATUS_ACCESS_VIOLATION);
2791 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
2792 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2793 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2799 *pcbStructInfo = sizeof(int);
2804 if (pbEncoded[0] == ASN_ENUMERATED)
2806 unsigned int val = 0, i;
2810 SetLastError(CRYPT_E_ASN1_EOD);
2813 else if (pbEncoded[1] == 0)
2815 SetLastError(CRYPT_E_ASN1_CORRUPT);
2820 /* A little strange looking, but we have to accept a sign byte:
2821 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
2822 * assuming a small length is okay here, it has to be in short
2825 if (pbEncoded[1] > sizeof(unsigned int) + 1)
2827 SetLastError(CRYPT_E_ASN1_LARGE);
2830 for (i = 0; i < pbEncoded[1]; i++)
2833 val |= pbEncoded[2 + i];
2835 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2836 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
2838 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2839 pvStructInfo = *(BYTE **)pvStructInfo;
2840 memcpy(pvStructInfo, &val, sizeof(unsigned int));
2846 SetLastError(CRYPT_E_ASN1_BADTAG);
2852 SetLastError(STATUS_ACCESS_VIOLATION);
2859 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
2862 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
2867 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
2869 if (!isdigit(*(pbEncoded))) \
2871 SetLastError(CRYPT_E_ASN1_CORRUPT); \
2877 (word) += *(pbEncoded)++ - '0'; \
2882 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
2883 SYSTEMTIME *sysTime)
2890 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
2892 WORD hours, minutes = 0;
2893 BYTE sign = *pbEncoded++;
2896 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
2897 if (ret && hours >= 24)
2899 SetLastError(CRYPT_E_ASN1_CORRUPT);
2904 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
2905 if (ret && minutes >= 60)
2907 SetLastError(CRYPT_E_ASN1_CORRUPT);
2915 sysTime->wHour += hours;
2916 sysTime->wMinute += minutes;
2920 if (hours > sysTime->wHour)
2923 sysTime->wHour = 24 - (hours - sysTime->wHour);
2926 sysTime->wHour -= hours;
2927 if (minutes > sysTime->wMinute)
2930 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
2933 sysTime->wMinute -= minutes;
2940 SetLastError(STATUS_ACCESS_VIOLATION);
2947 #define MIN_ENCODED_TIME_LENGTH 10
2949 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
2950 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2951 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2957 *pcbStructInfo = sizeof(FILETIME);
2963 if (pbEncoded[0] == ASN_UTCTIME)
2967 SetLastError(CRYPT_E_ASN1_EOD);
2970 else if (pbEncoded[1] > 0x7f)
2972 /* long-form date strings really can't be valid */
2973 SetLastError(CRYPT_E_ASN1_CORRUPT);
2978 SYSTEMTIME sysTime = { 0 };
2979 BYTE len = pbEncoded[1];
2981 if (len < MIN_ENCODED_TIME_LENGTH)
2983 SetLastError(CRYPT_E_ASN1_CORRUPT);
2989 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
2990 if (sysTime.wYear >= 50)
2991 sysTime.wYear += 1900;
2993 sysTime.wYear += 2000;
2994 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2995 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2996 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2997 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3000 if (len >= 2 && isdigit(*pbEncoded) &&
3001 isdigit(*(pbEncoded + 1)))
3002 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3004 else if (isdigit(*pbEncoded))
3005 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3008 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3011 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3012 pDecodePara, pvStructInfo, pcbStructInfo,
3015 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3016 pvStructInfo = *(BYTE **)pvStructInfo;
3017 ret = SystemTimeToFileTime(&sysTime,
3018 (FILETIME *)pvStructInfo);
3025 SetLastError(CRYPT_E_ASN1_BADTAG);
3031 SetLastError(STATUS_ACCESS_VIOLATION);
3038 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3039 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3040 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3046 *pcbStructInfo = sizeof(FILETIME);
3052 if (pbEncoded[0] == ASN_GENERALTIME)
3056 SetLastError(CRYPT_E_ASN1_EOD);
3059 else if (pbEncoded[1] > 0x7f)
3061 /* long-form date strings really can't be valid */
3062 SetLastError(CRYPT_E_ASN1_CORRUPT);
3067 BYTE len = pbEncoded[1];
3069 if (len < MIN_ENCODED_TIME_LENGTH)
3071 SetLastError(CRYPT_E_ASN1_CORRUPT);
3076 SYSTEMTIME sysTime = { 0 };
3079 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3080 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3081 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3082 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3085 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3088 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3090 if (ret && len > 0 && (*pbEncoded == '.' ||
3097 /* workaround macro weirdness */
3098 digits = min(len, 3);
3099 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3100 sysTime.wMilliseconds);
3103 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3106 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3107 pDecodePara, pvStructInfo, pcbStructInfo,
3110 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3111 pvStructInfo = *(BYTE **)pvStructInfo;
3112 ret = SystemTimeToFileTime(&sysTime,
3113 (FILETIME *)pvStructInfo);
3120 SetLastError(CRYPT_E_ASN1_BADTAG);
3126 SetLastError(STATUS_ACCESS_VIOLATION);
3133 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3134 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3135 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3141 if (pbEncoded[0] == ASN_UTCTIME)
3142 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3143 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3145 else if (pbEncoded[0] == ASN_GENERALTIME)
3146 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3147 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3148 pvStructInfo, pcbStructInfo);
3151 SetLastError(CRYPT_E_ASN1_BADTAG);
3157 SetLastError(STATUS_ACCESS_VIOLATION);
3164 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3165 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3166 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3172 if (pbEncoded[0] == ASN_SEQUENCEOF)
3174 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3176 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3181 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3182 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3184 ptr = pbEncoded + 1 + lenBytes;
3185 remainingLen = dataLen;
3186 while (ret && remainingLen)
3190 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3193 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3195 remainingLen -= 1 + nextLenBytes + nextLen;
3196 ptr += 1 + nextLenBytes + nextLen;
3197 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3198 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3199 bytesNeeded += 1 + nextLenBytes + nextLen;
3205 CRYPT_SEQUENCE_OF_ANY *seq;
3209 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3210 pvStructInfo, pcbStructInfo, bytesNeeded)))
3212 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3213 pvStructInfo = *(BYTE **)pvStructInfo;
3214 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3215 seq->cValue = cValue;
3216 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3218 nextPtr = (BYTE *)seq->rgValue +
3219 cValue * sizeof(CRYPT_DER_BLOB);
3220 ptr = pbEncoded + 1 + lenBytes;
3221 remainingLen = dataLen;
3223 while (ret && remainingLen)
3227 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3230 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3232 seq->rgValue[i].cbData = 1 + nextLenBytes +
3234 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3235 seq->rgValue[i].pbData = (BYTE *)ptr;
3238 seq->rgValue[i].pbData = nextPtr;
3239 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3241 nextPtr += 1 + nextLenBytes + nextLen;
3243 remainingLen -= 1 + nextLenBytes + nextLen;
3244 ptr += 1 + nextLenBytes + nextLen;
3254 SetLastError(CRYPT_E_ASN1_BADTAG);
3260 SetLastError(STATUS_ACCESS_VIOLATION);
3267 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3268 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3269 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3273 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3275 DWORD bytesNeeded, dataLen;
3277 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3279 struct AsnArrayDescriptor arrayDesc = {
3280 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3281 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3282 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3283 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3289 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3290 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3291 0, NULL, NULL, &nameLen, NULL);
3292 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3295 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3297 *pcbStructInfo = bytesNeeded;
3298 else if (*pcbStructInfo < bytesNeeded)
3300 *pcbStructInfo = bytesNeeded;
3301 SetLastError(ERROR_MORE_DATA);
3306 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3310 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3311 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3312 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3313 0, NULL, &name->u.FullName, pcbStructInfo,
3314 name->u.FullName.rgAltEntry);
3317 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3323 SetLastError(CRYPT_E_ASN1_BADTAG);
3329 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3330 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3331 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3333 struct AsnDecodeSequenceItem items[] = {
3334 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3335 DistPointName), CRYPT_AsnDecodeDistPointName,
3336 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3337 DistPointName.u.FullName.rgAltEntry), 0 },
3338 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3339 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3340 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3341 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3342 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3343 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3347 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3348 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3349 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3353 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3354 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3355 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3359 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3360 pDecodePara, pvStructInfo, *pcbStructInfo);
3364 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3365 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3366 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3368 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3369 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3373 SetLastError(STATUS_ACCESS_VIOLATION);
3380 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3381 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3382 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3386 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3387 pDecodePara, pvStructInfo, *pcbStructInfo);
3391 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3392 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3394 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3395 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3399 SetLastError(STATUS_ACCESS_VIOLATION);
3406 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3407 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3408 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3412 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3413 pDecodePara, pvStructInfo, *pcbStructInfo);
3417 struct AsnDecodeSequenceItem items[] = {
3418 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3419 DistPointName), CRYPT_AsnDecodeDistPointName,
3420 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3421 offsetof(CRL_ISSUING_DIST_POINT,
3422 DistPointName.u.FullName.rgAltEntry), 0 },
3423 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3424 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3426 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3427 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3429 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3430 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3431 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3432 OnlySomeReasonFlags.pbData), 0 },
3433 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3434 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3437 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3438 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3439 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3443 SetLastError(STATUS_ACCESS_VIOLATION);
3450 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3451 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3452 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3454 static HCRYPTOIDFUNCSET set = NULL;
3456 CryptDecodeObjectExFunc decodeFunc = NULL;
3457 HCRYPTOIDFUNCADDR hFunc = NULL;
3459 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
3460 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
3461 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3463 if (!pvStructInfo && !pcbStructInfo)
3465 SetLastError(ERROR_INVALID_PARAMETER);
3468 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3469 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3471 SetLastError(ERROR_FILE_NOT_FOUND);
3476 SetLastError(CRYPT_E_ASN1_EOD);
3479 if (cbEncoded > MAX_ENCODED_LEN)
3481 SetLastError(CRYPT_E_ASN1_LARGE);
3485 SetLastError(NOERROR);
3486 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3487 *(BYTE **)pvStructInfo = NULL;
3488 if (!HIWORD(lpszStructType))
3490 switch (LOWORD(lpszStructType))
3492 case (WORD)X509_CERT:
3493 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3495 case (WORD)X509_CERT_TO_BE_SIGNED:
3496 decodeFunc = CRYPT_AsnDecodeCert;
3498 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3499 decodeFunc = CRYPT_AsnDecodeCRL;
3501 case (WORD)X509_EXTENSIONS:
3502 decodeFunc = CRYPT_AsnDecodeExtensions;
3504 case (WORD)X509_NAME_VALUE:
3505 decodeFunc = CRYPT_AsnDecodeNameValue;
3507 case (WORD)X509_NAME:
3508 decodeFunc = CRYPT_AsnDecodeName;
3510 case (WORD)X509_PUBLIC_KEY_INFO:
3511 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
3513 case (WORD)X509_AUTHORITY_KEY_ID:
3514 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3516 case (WORD)X509_ALTERNATE_NAME:
3517 decodeFunc = CRYPT_AsnDecodeAltName;
3519 case (WORD)X509_BASIC_CONSTRAINTS:
3520 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3522 case (WORD)X509_BASIC_CONSTRAINTS2:
3523 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3525 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3526 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3528 case (WORD)X509_UNICODE_NAME:
3529 decodeFunc = CRYPT_AsnDecodeUnicodeName;
3531 case (WORD)X509_UNICODE_NAME_VALUE:
3532 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
3534 case (WORD)X509_OCTET_STRING:
3535 decodeFunc = CRYPT_AsnDecodeOctets;
3537 case (WORD)X509_BITS:
3538 case (WORD)X509_KEY_USAGE:
3539 decodeFunc = CRYPT_AsnDecodeBits;
3541 case (WORD)X509_INTEGER:
3542 decodeFunc = CRYPT_AsnDecodeInt;
3544 case (WORD)X509_MULTI_BYTE_INTEGER:
3545 decodeFunc = CRYPT_AsnDecodeInteger;
3547 case (WORD)X509_MULTI_BYTE_UINT:
3548 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3550 case (WORD)X509_ENUMERATED:
3551 decodeFunc = CRYPT_AsnDecodeEnumerated;
3553 case (WORD)X509_CHOICE_OF_TIME:
3554 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3556 case (WORD)X509_SEQUENCE_OF_ANY:
3557 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3559 case (WORD)PKCS_UTC_TIME:
3560 decodeFunc = CRYPT_AsnDecodeUtcTime;
3562 case (WORD)X509_CRL_DIST_POINTS:
3563 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3565 case (WORD)X509_ENHANCED_KEY_USAGE:
3566 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3568 case (WORD)X509_ISSUING_DIST_POINT:
3569 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3572 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3575 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3576 decodeFunc = CRYPT_AsnDecodeExtensions;
3577 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3578 decodeFunc = CRYPT_AsnDecodeUtcTime;
3579 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3580 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3581 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3582 decodeFunc = CRYPT_AsnDecodeEnumerated;
3583 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3584 decodeFunc = CRYPT_AsnDecodeBits;
3585 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3586 decodeFunc = CRYPT_AsnDecodeOctets;
3587 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3588 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3589 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3590 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3591 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3592 decodeFunc = CRYPT_AsnDecodeAltName;
3593 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3594 decodeFunc = CRYPT_AsnDecodeAltName;
3595 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3596 decodeFunc = CRYPT_AsnDecodeAltName;
3597 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3598 decodeFunc = CRYPT_AsnDecodeAltName;
3599 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3600 decodeFunc = CRYPT_AsnDecodeAltName;
3601 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3602 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3603 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3604 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3605 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3606 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3608 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3609 debugstr_a(lpszStructType));
3613 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
3614 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3615 (void **)&decodeFunc, &hFunc);
3618 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3619 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3621 SetLastError(ERROR_FILE_NOT_FOUND);
3623 CryptFreeOIDFunctionAddress(hFunc, 0);