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
118 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
119 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
120 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
121 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
122 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
123 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
124 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
125 void *pvStructInfo, DWORD *pcbStructInfo);
127 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
128 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
129 DWORD *pcbStructInfo)
131 static HCRYPTOIDFUNCSET set = NULL;
133 CryptDecodeObjectFunc pCryptDecodeObject;
134 HCRYPTOIDFUNCADDR hFunc;
136 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType,
137 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
138 pvStructInfo, pcbStructInfo);
140 if (!pvStructInfo && !pcbStructInfo)
142 SetLastError(ERROR_INVALID_PARAMETER);
146 /* Try registered DLL first.. */
148 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
149 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
150 (void **)&pCryptDecodeObject, &hFunc);
151 if (pCryptDecodeObject)
153 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
154 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
155 CryptFreeOIDFunctionAddress(hFunc, 0);
159 /* If not, use CryptDecodeObjectEx */
160 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
161 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
166 /* Gets the number of length bytes from the given (leading) length byte */
167 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
169 /* Helper function to get the encoded length of the data starting at pbEncoded,
170 * where pbEncoded[0] is the tag. If the data are too short to contain a
171 * length or if the length is too large for cbEncoded, sets an appropriate
172 * error code and returns FALSE.
174 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
181 SetLastError(CRYPT_E_ASN1_CORRUPT);
184 else if (pbEncoded[1] <= 0x7f)
186 if (pbEncoded[1] + 1 > cbEncoded)
188 SetLastError(CRYPT_E_ASN1_EOD);
199 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
201 if (lenLen > sizeof(DWORD) + 1)
203 SetLastError(CRYPT_E_ASN1_LARGE);
206 else if (lenLen + 2 > cbEncoded)
208 SetLastError(CRYPT_E_ASN1_CORRUPT);
221 if (out + lenLen + 1 > cbEncoded)
223 SetLastError(CRYPT_E_ASN1_EOD);
236 /* Helper function to check *pcbStructInfo, set it to the required size, and
237 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
238 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
239 * pointer to the newly allocated memory.
241 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
242 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
247 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
249 if (pDecodePara && pDecodePara->pfnAlloc)
250 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
252 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
253 if (!*(BYTE **)pvStructInfo)
256 *pcbStructInfo = bytesNeeded;
258 else if (*pcbStructInfo < bytesNeeded)
260 *pcbStructInfo = bytesNeeded;
261 SetLastError(ERROR_MORE_DATA);
268 * The expected tag of the item. If tag is 0, decodeFunc is called
269 * regardless of the tag value seen.
271 * A sequence is decoded into a struct. The offset member is the
272 * offset of this item within that struct.
274 * The decoder function to use. If this is NULL, then the member isn't
275 * decoded, but minSize space is reserved for it.
277 * The minimum amount of space occupied after decoding. You must set this.
279 * If true, and the tag doesn't match the expected tag for this item,
280 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
281 * filled with 0 for this member.
282 * hasPointer, pointerOffset, minSize:
283 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
284 * the offset within the (outer) struct of the data pointer (or to the
285 * first data pointer, if more than one exist).
287 * Used by CRYPT_AsnDecodeSequence, not for your use.
289 struct AsnDecodeSequenceItem
293 CryptDecodeObjectExFunc decodeFunc;
301 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
302 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
303 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData)
309 ptr = pbEncoded + 1 + GET_LEN_BYTES(pbEncoded[1]);
310 for (i = 0, ret = TRUE; ret && i < cItem; i++)
312 if (cbEncoded - (ptr - pbEncoded) != 0)
316 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
319 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
321 if (ptr[0] == items[i].tag || !items[i].tag)
323 if (nextData && pvStructInfo && items[i].hasPointer)
325 TRACE("Setting next pointer to %p\n",
327 *(BYTE **)((BYTE *)pvStructInfo +
328 items[i].pointerOffset) = nextData;
330 if (items[i].decodeFunc)
333 TRACE("decoding item %ld\n", i);
335 TRACE("sizing item %ld\n", i);
336 ret = items[i].decodeFunc(dwCertEncodingType,
337 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
338 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
339 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
340 : NULL, &items[i].size);
343 if (nextData && items[i].hasPointer &&
344 items[i].size > items[i].minSize)
346 nextData += items[i].size - items[i].minSize;
347 /* align nextData to DWORD boundaries */
348 if (items[i].size % sizeof(DWORD))
349 nextData += sizeof(DWORD) - items[i].size %
352 /* Account for alignment padding */
353 if (items[i].size % sizeof(DWORD))
354 items[i].size += sizeof(DWORD) -
355 items[i].size % sizeof(DWORD);
356 ptr += 1 + nextItemLenBytes + nextItemLen;
358 else if (items[i].optional &&
359 GetLastError() == CRYPT_E_ASN1_BADTAG)
361 TRACE("skipping optional item %ld\n", i);
362 items[i].size = items[i].minSize;
363 SetLastError(NOERROR);
367 TRACE("item %ld failed: %08lx\n", i,
371 items[i].size = items[i].minSize;
373 else if (items[i].optional)
375 TRACE("skipping optional item %ld\n", i);
376 items[i].size = items[i].minSize;
380 TRACE("tag %02x doesn't match expected %02x\n",
381 ptr[0], items[i].tag);
382 SetLastError(CRYPT_E_ASN1_BADTAG);
387 else if (items[i].optional)
389 TRACE("missing optional item %ld, skipping\n", i);
390 items[i].size = items[i].minSize;
394 TRACE("not enough bytes for item %ld, failing\n", i);
395 SetLastError(CRYPT_E_ASN1_CORRUPT);
399 if (cbEncoded - (ptr - pbEncoded) != 0)
401 TRACE("%ld remaining bytes, failing\n", cbEncoded -
403 SetLastError(CRYPT_E_ASN1_CORRUPT);
409 /* This decodes an arbitrary sequence into a contiguous block of memory
410 * (basically, a struct.) Each element being decoded is described by a struct
411 * AsnDecodeSequenceItem, see above.
412 * startingPointer is an optional pointer to the first place where dynamic
413 * data will be stored. If you know the starting offset, you may pass it
414 * here. Otherwise, pass NULL, and one will be inferred from the items.
415 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
416 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
418 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
419 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
420 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
421 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
425 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded,
426 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
429 if (pbEncoded[0] == ASN_SEQUENCE)
433 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
437 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
438 cbEncoded, dwFlags, NULL, NULL);
441 DWORD bytesNeeded = 0, structSize = 0;
443 for (i = 0; i < cItem; i++)
445 bytesNeeded += items[i].size;
446 structSize += items[i].minSize;
449 *pcbStructInfo = bytesNeeded;
450 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
451 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
455 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
456 pvStructInfo = *(BYTE **)pvStructInfo;
458 nextData = (BYTE *)startingPointer;
460 nextData = (BYTE *)pvStructInfo + structSize;
461 memset(pvStructInfo, 0, structSize);
462 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
463 pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
470 SetLastError(CRYPT_E_ASN1_BADTAG);
473 TRACE("returning %d (%08lx)\n", ret, GetLastError());
478 * The expected tag of the entire encoded array (usually a variant
479 * of ASN_SETOF or ASN_SEQUENCEOF.)
481 * used to decode each item in the array
483 * is the minimum size of each decoded item
485 * indicates whether each item has a dynamic pointer
487 * indicates the offset within itemSize at which the pointer exists
489 struct AsnArrayDescriptor
492 CryptDecodeObjectExFunc decodeFunc;
498 struct AsnArrayItemSize
504 /* Decodes an array of like types into a struct GenericArray.
505 * The layout and decoding of the array are described by a struct
506 * AsnArrayDescriptor.
508 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
509 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
510 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
511 void *startingPointer)
515 TRACE("%p, %p, %ld, %08lx, %p, %p, %ld, %p\n", arrayDesc, pbEncoded,
516 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
519 if (pbEncoded[0] == arrayDesc->tag)
523 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
525 DWORD bytesNeeded, cItems = 0;
526 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
527 /* There can be arbitrarily many items, but there is often only one.
529 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
531 bytesNeeded = sizeof(struct GenericArray);
536 for (ptr = pbEncoded + 1 + lenBytes; ret &&
537 ptr - pbEncoded - 1 - lenBytes < dataLen; )
539 DWORD itemLenBytes, itemDataLen, size;
541 itemLenBytes = GET_LEN_BYTES(ptr[1]);
542 /* Each item decoded may not tolerate extraneous bytes, so
543 * get the length of the next element and pass it directly.
545 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
548 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
549 1 + itemLenBytes + itemDataLen,
550 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
557 if (itemSizes != &itemSize)
558 itemSizes = CryptMemRealloc(itemSizes,
559 cItems * sizeof(struct AsnArrayItemSize));
564 cItems * sizeof(struct AsnArrayItemSize));
566 memcpy(itemSizes, &itemSize, sizeof(itemSize));
570 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
572 itemSizes[cItems - 1].size = size;
574 ret = CRYPT_GetLen(ptr,
575 cbEncoded - (ptr - pbEncoded), &nextLen);
577 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
587 *pcbStructInfo = bytesNeeded;
588 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
589 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
594 struct GenericArray *array;
596 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
597 pvStructInfo = *(BYTE **)pvStructInfo;
598 array = (struct GenericArray *)pvStructInfo;
599 array->cItems = cItems;
601 array->rgItems = startingPointer;
603 array->rgItems = (BYTE *)array +
604 sizeof(struct GenericArray);
605 nextData = (BYTE *)array->rgItems +
606 array->cItems * arrayDesc->itemSize;
607 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
608 i < cItems && ptr - pbEncoded - 1 - lenBytes <
611 if (arrayDesc->hasPointer)
612 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
613 + arrayDesc->pointerOffset) = nextData;
614 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
615 itemSizes[i].encodedLen,
616 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
617 array->rgItems + i * arrayDesc->itemSize,
623 nextData += itemSizes[i].size - arrayDesc->itemSize;
624 ret = CRYPT_GetLen(ptr,
625 cbEncoded - (ptr - pbEncoded), &nextLen);
627 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
632 if (itemSizes != &itemSize)
633 CryptMemFree(itemSizes);
638 SetLastError(CRYPT_E_ASN1_BADTAG);
644 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
645 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
646 * to CRYPT_E_ASN1_CORRUPT.
647 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
650 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
651 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
652 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
657 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
659 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
660 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
662 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
663 bytesNeeded += 1 + lenBytes + dataLen;
666 *pcbStructInfo = bytesNeeded;
667 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
668 pvStructInfo, pcbStructInfo, bytesNeeded)))
670 CRYPT_DER_BLOB *blob;
672 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
673 pvStructInfo = *(BYTE **)pvStructInfo;
674 blob = (CRYPT_DER_BLOB *)pvStructInfo;
675 blob->cbData = 1 + lenBytes + dataLen;
678 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
679 blob->pbData = (BYTE *)pbEncoded;
682 assert(blob->pbData);
683 memcpy(blob->pbData, pbEncoded, blob->cbData);
688 SetLastError(CRYPT_E_ASN1_CORRUPT);
696 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
697 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
698 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
699 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
703 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
704 pDecodePara, pvStructInfo, *pcbStructInfo);
706 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
709 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
710 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
711 pvStructInfo, pcbStructInfo);
712 if (ret && pvStructInfo)
714 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
721 for (i = 0; i < blob->cbData / 2; i++)
723 temp = blob->pbData[i];
724 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
725 blob->pbData[blob->cbData - i - 1] = temp;
729 TRACE("returning %d (%08lx)\n", ret, GetLastError());
733 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
734 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
735 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
739 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
740 pDecodePara, pvStructInfo, *pcbStructInfo);
744 struct AsnDecodeSequenceItem items[] = {
745 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
746 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
747 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
748 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
749 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
750 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
751 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
752 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
753 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
754 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
757 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
758 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
759 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
760 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
761 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
765 SetLastError(STATUS_ACCESS_VIOLATION);
770 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
774 /* Internal function */
775 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
776 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
777 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
782 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
784 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
786 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
787 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
788 pvStructInfo, pcbStructInfo);
793 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
794 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
795 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
799 struct AsnDecodeSequenceItem items[] = {
800 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
801 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
802 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
803 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
806 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
807 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
808 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
812 /* Internal function */
813 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
814 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
815 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
820 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
822 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
824 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
825 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
826 pDecodePara, pvStructInfo, pcbStructInfo);
831 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
832 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
833 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
836 struct AsnDecodeSequenceItem items[] = {
837 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
838 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
839 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
840 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
841 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
842 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
843 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
844 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
845 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
846 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
848 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
849 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
851 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
852 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
854 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
855 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
856 FALSE, TRUE, offsetof(CERT_INFO,
857 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
858 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
859 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
860 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
861 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
862 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
863 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
864 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
865 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
866 offsetof(CERT_INFO, rgExtension), 0 },
869 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
870 pDecodePara, pvStructInfo, *pcbStructInfo);
872 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
873 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
874 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
876 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
880 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
881 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
882 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
886 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
887 pDecodePara, pvStructInfo, *pcbStructInfo);
891 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
894 /* First try to decode it as a signed cert. */
895 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
896 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
897 (BYTE *)&signedCert, &size);
901 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
902 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
903 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
905 LocalFree(signedCert);
907 /* Failing that, try it as an unsigned cert */
911 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
912 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
913 pDecodePara, pvStructInfo, pcbStructInfo);
918 SetLastError(STATUS_ACCESS_VIOLATION);
923 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
927 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
928 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
929 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
932 struct AsnDecodeSequenceItem items[] = {
933 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
934 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
935 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
936 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
937 sizeof(FILETIME), FALSE, FALSE, 0 },
938 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
939 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
940 offsetof(CRL_ENTRY, rgExtension), 0 },
942 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
944 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
947 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
948 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
949 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
953 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
954 * been set prior to calling.
956 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
957 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
958 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
961 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
962 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
963 offsetof(CRL_ENTRY, SerialNumber.pbData) };
964 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
966 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
967 pDecodePara, pvStructInfo, *pcbStructInfo);
969 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
970 pDecodePara, pvStructInfo, pcbStructInfo,
971 entries ? entries->rgItems : NULL);
972 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
976 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
977 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
978 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
980 struct AsnDecodeSequenceItem items[] = {
981 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
982 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
983 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
984 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
985 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
986 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
987 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
989 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
990 sizeof(FILETIME), FALSE, FALSE, 0 },
991 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
992 sizeof(FILETIME), TRUE, FALSE, 0 },
993 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
994 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
995 offsetof(CRL_INFO, rgCRLEntry), 0 },
996 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
997 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
998 offsetof(CRL_INFO, rgExtension), 0 },
1002 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1003 pDecodePara, pvStructInfo, *pcbStructInfo);
1005 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1006 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1007 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1009 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1013 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1014 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1015 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1019 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1020 pDecodePara, pvStructInfo, *pcbStructInfo);
1024 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1027 /* First try to decode it as a signed crl. */
1028 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1029 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1030 (BYTE *)&signedCrl, &size);
1034 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1035 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1036 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1037 pvStructInfo, pcbStructInfo);
1038 LocalFree(signedCrl);
1040 /* Failing that, try it as an unsigned crl */
1044 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1045 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1046 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1051 SetLastError(STATUS_ACCESS_VIOLATION);
1056 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1060 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1061 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1062 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1066 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1067 pDecodePara, pvStructInfo, *pcbStructInfo);
1069 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1073 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1075 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1076 DWORD bytesNeeded = sizeof(LPSTR);
1080 /* The largest possible string for the first two components
1081 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1086 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1087 pbEncoded[1 + lenBytes] / 40,
1088 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1090 bytesNeeded += strlen(firstTwo) + 1;
1091 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1092 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1094 /* large enough for ".4000000" */
1098 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1105 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1108 SetLastError(CRYPT_E_ASN1_CORRUPT);
1115 snprintf(str, sizeof(str), ".%d", val);
1116 bytesNeeded += strlen(str);
1121 *pcbStructInfo = bytesNeeded;
1122 else if (*pcbStructInfo < bytesNeeded)
1124 *pcbStructInfo = bytesNeeded;
1125 SetLastError(ERROR_MORE_DATA);
1133 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1136 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1137 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1139 pszObjId += strlen(pszObjId);
1140 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1141 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1145 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1154 sprintf(pszObjId, ".%d", val);
1155 pszObjId += strlen(pszObjId);
1159 *(LPSTR *)pvStructInfo = NULL;
1160 *pcbStructInfo = bytesNeeded;
1167 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1170 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1171 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1172 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1174 struct AsnDecodeSequenceItem items[] = {
1175 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1176 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1177 offsetof(CERT_EXTENSION, pszObjId), 0 },
1178 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1179 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1180 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1181 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1182 offsetof(CERT_EXTENSION, Value.pbData) },
1185 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1187 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
1191 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1192 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1193 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1194 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1196 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1197 debugstr_a(ext->pszObjId));
1198 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1202 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1203 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1204 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1207 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1208 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1209 offsetof(CERT_EXTENSION, pszObjId) };
1210 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1212 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1213 pDecodePara, pvStructInfo, *pcbStructInfo);
1215 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1216 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1220 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1221 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1222 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1228 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1229 lpszStructType, pbEncoded, cbEncoded,
1230 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1231 if (ret && pvStructInfo)
1233 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1234 pcbStructInfo, *pcbStructInfo);
1237 CERT_EXTENSIONS *exts;
1239 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1240 pvStructInfo = *(BYTE **)pvStructInfo;
1241 exts = (CERT_EXTENSIONS *)pvStructInfo;
1242 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1243 sizeof(CERT_EXTENSIONS));
1244 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1245 lpszStructType, pbEncoded, cbEncoded,
1246 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1253 SetLastError(STATUS_ACCESS_VIOLATION);
1260 /* Warning: this assumes the address of value->Value.pbData is already set, in
1261 * order to avoid overwriting memory. (In some cases, it may change it, if it
1262 * doesn't copy anything to memory.) Be sure to set it correctly!
1264 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1265 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1266 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1270 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1272 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1274 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1275 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1277 switch (pbEncoded[0])
1279 case ASN_OCTETSTRING:
1280 valueType = CERT_RDN_OCTET_STRING;
1281 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1282 bytesNeeded += dataLen;
1284 case ASN_NUMERICSTRING:
1285 valueType = CERT_RDN_NUMERIC_STRING;
1286 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1287 bytesNeeded += dataLen;
1289 case ASN_PRINTABLESTRING:
1290 valueType = CERT_RDN_PRINTABLE_STRING;
1291 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1292 bytesNeeded += dataLen;
1295 valueType = CERT_RDN_IA5_STRING;
1296 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1297 bytesNeeded += dataLen;
1300 valueType = CERT_RDN_T61_STRING;
1301 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1302 bytesNeeded += dataLen;
1304 case ASN_VIDEOTEXSTRING:
1305 valueType = CERT_RDN_VIDEOTEX_STRING;
1306 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1307 bytesNeeded += dataLen;
1309 case ASN_GRAPHICSTRING:
1310 valueType = CERT_RDN_GRAPHIC_STRING;
1311 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1312 bytesNeeded += dataLen;
1314 case ASN_VISIBLESTRING:
1315 valueType = CERT_RDN_VISIBLE_STRING;
1316 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1317 bytesNeeded += dataLen;
1319 case ASN_GENERALSTRING:
1320 valueType = CERT_RDN_GENERAL_STRING;
1321 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1322 bytesNeeded += dataLen;
1324 case ASN_UNIVERSALSTRING:
1325 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1326 SetLastError(CRYPT_E_ASN1_BADTAG);
1329 valueType = CERT_RDN_BMP_STRING;
1330 bytesNeeded += dataLen;
1332 case ASN_UTF8STRING:
1333 valueType = CERT_RDN_UTF8_STRING;
1334 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1335 (LPSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1338 SetLastError(CRYPT_E_ASN1_BADTAG);
1343 *pcbStructInfo = bytesNeeded;
1344 else if (*pcbStructInfo < bytesNeeded)
1346 *pcbStructInfo = bytesNeeded;
1347 SetLastError(ERROR_MORE_DATA);
1352 *pcbStructInfo = bytesNeeded;
1353 value->dwValueType = valueType;
1358 assert(value->Value.pbData);
1359 switch (pbEncoded[0])
1361 case ASN_OCTETSTRING:
1362 case ASN_NUMERICSTRING:
1363 case ASN_PRINTABLESTRING:
1366 case ASN_VIDEOTEXSTRING:
1367 case ASN_GRAPHICSTRING:
1368 case ASN_VISIBLESTRING:
1369 case ASN_GENERALSTRING:
1370 value->Value.cbData = dataLen;
1373 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1374 memcpy(value->Value.pbData,
1375 pbEncoded + 1 + lenBytes, dataLen);
1377 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1383 LPWSTR str = (LPWSTR)value->Value.pbData;
1385 value->Value.cbData = dataLen;
1386 for (i = 0; i < dataLen / 2; i++)
1387 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1388 pbEncoded[1 + lenBytes + 2 * i + 1];
1391 case ASN_UTF8STRING:
1393 LPWSTR str = (LPWSTR)value->Value.pbData;
1395 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1396 (LPSTR)pbEncoded + 1 + lenBytes, dataLen,
1397 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1404 value->Value.cbData = 0;
1405 value->Value.pbData = NULL;
1412 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1413 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1414 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1420 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1421 lpszStructType, pbEncoded, cbEncoded,
1422 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1423 if (ret && pvStructInfo)
1425 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1426 pcbStructInfo, *pcbStructInfo);
1429 CERT_NAME_VALUE *value;
1431 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1432 pvStructInfo = *(BYTE **)pvStructInfo;
1433 value = (CERT_NAME_VALUE *)pvStructInfo;
1434 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1435 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1436 lpszStructType, pbEncoded, cbEncoded,
1437 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1444 SetLastError(STATUS_ACCESS_VIOLATION);
1451 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1452 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1453 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1454 void *pvStructInfo, DWORD *pcbStructInfo)
1458 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1460 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1462 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1463 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1465 switch (pbEncoded[0])
1467 case ASN_NUMERICSTRING:
1468 valueType = CERT_RDN_NUMERIC_STRING;
1469 bytesNeeded += dataLen * 2;
1471 case ASN_PRINTABLESTRING:
1472 valueType = CERT_RDN_PRINTABLE_STRING;
1473 bytesNeeded += dataLen * 2;
1476 valueType = CERT_RDN_IA5_STRING;
1477 bytesNeeded += dataLen * 2;
1480 valueType = CERT_RDN_T61_STRING;
1481 bytesNeeded += dataLen * 2;
1483 case ASN_VIDEOTEXSTRING:
1484 valueType = CERT_RDN_VIDEOTEX_STRING;
1485 bytesNeeded += dataLen * 2;
1487 case ASN_GRAPHICSTRING:
1488 valueType = CERT_RDN_GRAPHIC_STRING;
1489 bytesNeeded += dataLen * 2;
1491 case ASN_VISIBLESTRING:
1492 valueType = CERT_RDN_VISIBLE_STRING;
1493 bytesNeeded += dataLen * 2;
1495 case ASN_GENERALSTRING:
1496 valueType = CERT_RDN_GENERAL_STRING;
1497 bytesNeeded += dataLen * 2;
1499 case ASN_UNIVERSALSTRING:
1500 valueType = CERT_RDN_UNIVERSAL_STRING;
1501 bytesNeeded += dataLen / 2;
1504 valueType = CERT_RDN_BMP_STRING;
1505 bytesNeeded += dataLen;
1507 case ASN_UTF8STRING:
1508 valueType = CERT_RDN_UTF8_STRING;
1509 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1510 (LPSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1513 SetLastError(CRYPT_E_ASN1_BADTAG);
1518 *pcbStructInfo = bytesNeeded;
1519 else if (*pcbStructInfo < bytesNeeded)
1521 *pcbStructInfo = bytesNeeded;
1522 SetLastError(ERROR_MORE_DATA);
1527 *pcbStructInfo = bytesNeeded;
1528 value->dwValueType = valueType;
1532 LPWSTR str = (LPWSTR)value->Value.pbData;
1534 assert(value->Value.pbData);
1535 switch (pbEncoded[0])
1537 case ASN_NUMERICSTRING:
1538 case ASN_PRINTABLESTRING:
1541 case ASN_VIDEOTEXSTRING:
1542 case ASN_GRAPHICSTRING:
1543 case ASN_VISIBLESTRING:
1544 case ASN_GENERALSTRING:
1545 value->Value.cbData = dataLen * 2;
1546 for (i = 0; i < dataLen; i++)
1547 str[i] = pbEncoded[1 + lenBytes + i];
1549 case ASN_UNIVERSALSTRING:
1550 value->Value.cbData = dataLen / 2;
1551 for (i = 0; i < dataLen / 4; i++)
1552 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1553 | pbEncoded[1 + lenBytes + 2 * i + 3];
1556 value->Value.cbData = dataLen;
1557 for (i = 0; i < dataLen / 2; i++)
1558 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1559 pbEncoded[1 + lenBytes + 2 * i + 1];
1561 case ASN_UTF8STRING:
1562 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1563 (LPSTR)pbEncoded + 1 + lenBytes, dataLen,
1564 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1570 value->Value.cbData = 0;
1571 value->Value.pbData = NULL;
1578 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1579 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1580 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1586 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1587 lpszStructType, pbEncoded, cbEncoded,
1588 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1589 if (ret && pvStructInfo)
1591 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1592 pcbStructInfo, *pcbStructInfo);
1595 CERT_NAME_VALUE *value;
1597 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1598 pvStructInfo = *(BYTE **)pvStructInfo;
1599 value = (CERT_NAME_VALUE *)pvStructInfo;
1600 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1601 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1602 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1603 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1610 SetLastError(STATUS_ACCESS_VIOLATION);
1617 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1618 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1619 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1622 struct AsnDecodeSequenceItem items[] = {
1623 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1624 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1625 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1626 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1627 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1628 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1630 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1632 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1633 pvStructInfo, *pcbStructInfo);
1636 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1637 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1638 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1639 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1642 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1643 debugstr_a(attr->pszObjId));
1644 TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1646 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1650 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1651 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1652 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1655 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1656 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1657 offsetof(CERT_RDN_ATTR, pszObjId) };
1658 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1660 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1661 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1665 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1666 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1667 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1673 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1674 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1675 offsetof(CERT_RDN, rgRDNAttr) };
1677 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1678 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1682 SetLastError(STATUS_ACCESS_VIOLATION);
1689 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
1690 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1691 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1694 struct AsnDecodeSequenceItem items[] = {
1695 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1696 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1697 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1698 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1699 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1700 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1702 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1704 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1705 pvStructInfo, *pcbStructInfo);
1708 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1709 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1710 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1711 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1714 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1715 debugstr_a(attr->pszObjId));
1716 TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1718 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1722 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
1723 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1724 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1727 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1728 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1729 offsetof(CERT_RDN_ATTR, pszObjId) };
1730 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1732 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1733 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1737 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1738 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1739 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1745 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1746 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1747 offsetof(CERT_RDN, rgRDNAttr) };
1749 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1750 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1754 SetLastError(STATUS_ACCESS_VIOLATION);
1761 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1762 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1763 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1766 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1768 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1769 pDecodePara, pvStructInfo, *pcbStructInfo);
1771 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1772 bytesNeeded += cbEncoded;
1774 *pcbStructInfo = bytesNeeded;
1775 else if (*pcbStructInfo < bytesNeeded)
1777 SetLastError(ERROR_MORE_DATA);
1778 *pcbStructInfo = bytesNeeded;
1783 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1785 *pcbStructInfo = bytesNeeded;
1786 blob->cbData = cbEncoded;
1787 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1788 blob->pbData = (LPBYTE)pbEncoded;
1791 assert(blob->pbData);
1792 memcpy(blob->pbData, pbEncoded, blob->cbData);
1798 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1799 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1800 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1802 CRYPT_ALGORITHM_IDENTIFIER *algo =
1803 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1805 struct AsnDecodeSequenceItem items[] = {
1806 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1807 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1808 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1809 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1810 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1811 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1814 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1815 pDecodePara, pvStructInfo, *pcbStructInfo);
1817 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1818 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1819 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1820 if (ret && pvStructInfo)
1822 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1823 debugstr_a(algo->pszObjId));
1828 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1829 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1830 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1833 struct AsnDecodeSequenceItem items[] = {
1834 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1835 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1836 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1837 Algorithm.pszObjId) },
1838 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1839 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1840 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1842 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1844 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1845 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1846 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1847 info->Algorithm.Parameters.pbData : NULL);
1851 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1852 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1853 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1861 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1862 lpszStructType, pbEncoded, cbEncoded,
1863 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1866 *pcbStructInfo = bytesNeeded;
1867 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1868 pvStructInfo, pcbStructInfo, bytesNeeded)))
1870 PCERT_PUBLIC_KEY_INFO info;
1872 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1873 pvStructInfo = *(BYTE **)pvStructInfo;
1874 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1875 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
1876 sizeof(CERT_PUBLIC_KEY_INFO);
1877 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1878 lpszStructType, pbEncoded, cbEncoded,
1879 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1886 SetLastError(STATUS_ACCESS_VIOLATION);
1893 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
1894 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1895 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1901 SetLastError(CRYPT_E_ASN1_CORRUPT);
1904 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
1906 SetLastError(CRYPT_E_ASN1_CORRUPT);
1909 if (pbEncoded[1] > 1)
1911 SetLastError(CRYPT_E_ASN1_CORRUPT);
1916 *pcbStructInfo = sizeof(BOOL);
1919 else if (*pcbStructInfo < sizeof(BOOL))
1921 *pcbStructInfo = sizeof(BOOL);
1922 SetLastError(ERROR_MORE_DATA);
1927 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
1930 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1934 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
1935 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1936 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1938 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
1939 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
1942 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1943 pDecodePara, pvStructInfo, *pcbStructInfo);
1947 SetLastError(CRYPT_E_ASN1_CORRUPT);
1950 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
1952 SetLastError(CRYPT_E_ASN1_BADTAG);
1955 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1956 if (1 + lenBytes > cbEncoded)
1958 SetLastError(CRYPT_E_ASN1_CORRUPT);
1961 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1963 switch (pbEncoded[0] & ASN_TYPE_MASK)
1965 case 1: /* rfc822Name */
1966 case 2: /* dNSName */
1967 case 6: /* uniformResourceIdentifier */
1968 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1970 case 7: /* iPAddress */
1971 bytesNeeded += dataLen;
1973 case 8: /* registeredID */
1974 /* FIXME: decode as OID */
1975 case 0: /* otherName */
1976 case 4: /* directoryName */
1978 SetLastError(CRYPT_E_ASN1_BADTAG);
1981 case 3: /* x400Address, unimplemented */
1982 case 5: /* ediPartyName, unimplemented */
1983 SetLastError(CRYPT_E_ASN1_BADTAG);
1987 SetLastError(CRYPT_E_ASN1_CORRUPT);
1993 *pcbStructInfo = bytesNeeded;
1994 else if (*pcbStructInfo < bytesNeeded)
1996 *pcbStructInfo = bytesNeeded;
1997 SetLastError(ERROR_MORE_DATA);
2002 *pcbStructInfo = bytesNeeded;
2003 /* MS used values one greater than the asn1 ones.. sigh */
2004 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2005 switch (pbEncoded[0] & ASN_TYPE_MASK)
2007 case 1: /* rfc822Name */
2008 case 2: /* dNSName */
2009 case 6: /* uniformResourceIdentifier */
2013 for (i = 0; i < dataLen; i++)
2014 entry->u.pwszURL[i] =
2015 (WCHAR)pbEncoded[1 + lenBytes + i];
2016 entry->u.pwszURL[i] = 0;
2017 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2018 debugstr_w(entry->u.pwszURL));
2021 case 7: /* iPAddress */
2022 /* The next data pointer is in the pwszURL spot, that is,
2023 * the first 4 bytes. Need to move it to the next spot.
2025 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2026 entry->u.IPAddress.cbData = dataLen;
2027 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2037 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2038 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2039 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2042 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2043 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2044 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2045 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2047 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2048 pDecodePara, pvStructInfo, *pcbStructInfo);
2051 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2052 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2053 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2057 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2058 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2059 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2063 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2064 pDecodePara, pvStructInfo, *pcbStructInfo);
2068 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2069 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2070 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2072 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2073 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2077 SetLastError(STATUS_ACCESS_VIOLATION);
2084 struct PATH_LEN_CONSTRAINT
2086 BOOL fPathLenConstraint;
2087 DWORD dwPathLenConstraint;
2090 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2091 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2092 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2096 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2097 pvStructInfo, *pcbStructInfo);
2101 if (pbEncoded[0] == ASN_INTEGER)
2103 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2106 *pcbStructInfo = bytesNeeded;
2107 else if (*pcbStructInfo < bytesNeeded)
2109 SetLastError(ERROR_MORE_DATA);
2110 *pcbStructInfo = bytesNeeded;
2115 struct PATH_LEN_CONSTRAINT *constraint =
2116 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2117 DWORD size = sizeof(constraint->dwPathLenConstraint);
2119 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2120 pbEncoded, cbEncoded, 0, NULL,
2121 &constraint->dwPathLenConstraint, &size);
2123 constraint->fPathLenConstraint = TRUE;
2124 TRACE("got an int, dwPathLenConstraint is %ld\n",
2125 constraint->dwPathLenConstraint);
2130 SetLastError(CRYPT_E_ASN1_CORRUPT);
2134 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2138 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2139 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2140 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2143 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2144 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2145 offsetof(CERT_NAME_BLOB, pbData) };
2146 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2148 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2149 pDecodePara, pvStructInfo, *pcbStructInfo);
2151 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2152 pDecodePara, pvStructInfo, pcbStructInfo,
2153 entries ? entries->rgItems : NULL);
2154 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
2158 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2159 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2160 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2166 struct AsnDecodeSequenceItem items[] = {
2167 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2168 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2169 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2170 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2171 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2172 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2173 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2174 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2175 sizeof(struct GenericArray), TRUE, TRUE,
2176 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2179 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2180 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2181 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2185 SetLastError(STATUS_ACCESS_VIOLATION);
2192 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2193 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2194 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2200 struct AsnDecodeSequenceItem items[] = {
2201 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2202 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2203 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2204 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2205 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2208 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2209 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2210 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2214 SetLastError(STATUS_ACCESS_VIOLATION);
2221 #define RSA1_MAGIC 0x31415352
2223 struct DECODED_RSA_PUB_KEY
2226 CRYPT_INTEGER_BLOB modulus;
2229 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2230 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2231 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2237 struct AsnDecodeSequenceItem items[] = {
2238 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2239 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2240 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2242 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2243 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2245 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2248 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2249 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2250 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2253 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2254 decodedKey->modulus.cbData;
2258 *pcbStructInfo = bytesNeeded;
2261 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2262 pvStructInfo, pcbStructInfo, bytesNeeded)))
2265 RSAPUBKEY *rsaPubKey;
2267 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2268 pvStructInfo = *(BYTE **)pvStructInfo;
2269 hdr = (BLOBHEADER *)pvStructInfo;
2270 hdr->bType = PUBLICKEYBLOB;
2271 hdr->bVersion = CUR_BLOB_VERSION;
2273 hdr->aiKeyAlg = CALG_RSA_KEYX;
2274 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2275 sizeof(BLOBHEADER));
2276 rsaPubKey->magic = RSA1_MAGIC;
2277 rsaPubKey->pubexp = decodedKey->pubexp;
2278 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2279 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2280 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2281 decodedKey->modulus.cbData);
2283 LocalFree(decodedKey);
2288 SetLastError(STATUS_ACCESS_VIOLATION);
2295 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2296 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2297 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2300 DWORD bytesNeeded, dataLen;
2302 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2303 pDecodePara, pvStructInfo, *pcbStructInfo);
2305 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2307 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2308 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2310 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2312 *pcbStructInfo = bytesNeeded;
2313 else if (*pcbStructInfo < bytesNeeded)
2315 SetLastError(ERROR_MORE_DATA);
2316 *pcbStructInfo = bytesNeeded;
2321 CRYPT_DATA_BLOB *blob;
2322 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2324 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2325 blob->cbData = dataLen;
2326 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2327 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2330 assert(blob->pbData);
2332 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2340 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2341 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2342 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2346 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2347 pDecodePara, pvStructInfo, *pcbStructInfo);
2355 SetLastError(CRYPT_E_ASN1_CORRUPT);
2358 else if (pbEncoded[0] != ASN_OCTETSTRING)
2360 SetLastError(CRYPT_E_ASN1_BADTAG);
2363 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2364 lpszStructType, pbEncoded, cbEncoded,
2365 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2368 *pcbStructInfo = bytesNeeded;
2369 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2370 pvStructInfo, pcbStructInfo, bytesNeeded)))
2372 CRYPT_DATA_BLOB *blob;
2374 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2375 pvStructInfo = *(BYTE **)pvStructInfo;
2376 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2377 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2378 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2379 lpszStructType, pbEncoded, cbEncoded,
2380 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2387 SetLastError(STATUS_ACCESS_VIOLATION);
2394 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2395 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2396 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2400 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2401 pDecodePara, pvStructInfo, *pcbStructInfo);
2403 if (pbEncoded[0] == ASN_BITSTRING)
2405 DWORD bytesNeeded, dataLen;
2407 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2409 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2410 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2412 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2414 *pcbStructInfo = bytesNeeded;
2415 else if (*pcbStructInfo < bytesNeeded)
2417 *pcbStructInfo = bytesNeeded;
2418 SetLastError(ERROR_MORE_DATA);
2423 CRYPT_BIT_BLOB *blob;
2425 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2426 blob->cbData = dataLen - 1;
2427 blob->cUnusedBits = *(pbEncoded + 1 +
2428 GET_LEN_BYTES(pbEncoded[1]));
2429 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2431 blob->pbData = (BYTE *)pbEncoded + 2 +
2432 GET_LEN_BYTES(pbEncoded[1]);
2436 assert(blob->pbData);
2439 BYTE mask = 0xff << blob->cUnusedBits;
2441 memcpy(blob->pbData, pbEncoded + 2 +
2442 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2443 blob->pbData[blob->cbData - 1] &= mask;
2451 SetLastError(CRYPT_E_ASN1_BADTAG);
2454 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2458 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2459 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2460 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2464 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2465 pDecodePara, pvStructInfo, pcbStructInfo);
2471 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2472 lpszStructType, pbEncoded, cbEncoded,
2473 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2476 *pcbStructInfo = bytesNeeded;
2477 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2478 pvStructInfo, pcbStructInfo, bytesNeeded)))
2480 CRYPT_BIT_BLOB *blob;
2482 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2483 pvStructInfo = *(BYTE **)pvStructInfo;
2484 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2485 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2486 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2487 lpszStructType, pbEncoded, cbEncoded,
2488 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2495 SetLastError(STATUS_ACCESS_VIOLATION);
2499 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2503 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2504 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2505 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2511 *pcbStructInfo = sizeof(int);
2516 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2517 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2518 DWORD size = sizeof(buf);
2520 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2521 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2522 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size);
2525 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2526 pvStructInfo, pcbStructInfo, sizeof(int))))
2530 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2531 pvStructInfo = *(BYTE **)pvStructInfo;
2532 if (blob->pbData[blob->cbData - 1] & 0x80)
2534 /* initialize to a negative value to sign-extend */
2539 for (i = 0; i < blob->cbData; i++)
2542 val |= blob->pbData[blob->cbData - i - 1];
2544 memcpy(pvStructInfo, &val, sizeof(int));
2547 else if (GetLastError() == ERROR_MORE_DATA)
2548 SetLastError(CRYPT_E_ASN1_LARGE);
2552 SetLastError(STATUS_ACCESS_VIOLATION);
2559 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2560 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2561 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2565 if (pbEncoded[0] == ASN_INTEGER)
2567 DWORD bytesNeeded, dataLen;
2569 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2571 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2573 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2575 *pcbStructInfo = bytesNeeded;
2576 else if (*pcbStructInfo < bytesNeeded)
2578 *pcbStructInfo = bytesNeeded;
2579 SetLastError(ERROR_MORE_DATA);
2584 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2586 blob->cbData = dataLen;
2587 assert(blob->pbData);
2592 for (i = 0; i < blob->cbData; i++)
2594 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2603 SetLastError(CRYPT_E_ASN1_BADTAG);
2609 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2610 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2611 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2619 if ((ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2620 lpszStructType, pbEncoded, cbEncoded,
2621 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2624 *pcbStructInfo = bytesNeeded;
2625 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2626 pvStructInfo, pcbStructInfo, bytesNeeded)))
2628 CRYPT_INTEGER_BLOB *blob;
2630 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2631 pvStructInfo = *(BYTE **)pvStructInfo;
2632 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2633 blob->pbData = (BYTE *)pvStructInfo +
2634 sizeof(CRYPT_INTEGER_BLOB);
2635 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2636 lpszStructType, pbEncoded, cbEncoded,
2637 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2644 SetLastError(STATUS_ACCESS_VIOLATION);
2651 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
2652 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2653 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2654 void *pvStructInfo, DWORD *pcbStructInfo)
2658 if (pbEncoded[0] == ASN_INTEGER)
2660 DWORD bytesNeeded, dataLen;
2662 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2664 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2666 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2668 *pcbStructInfo = bytesNeeded;
2669 else if (*pcbStructInfo < bytesNeeded)
2671 *pcbStructInfo = bytesNeeded;
2672 SetLastError(ERROR_MORE_DATA);
2677 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2679 blob->cbData = dataLen;
2680 assert(blob->pbData);
2681 /* remove leading zero byte if it exists */
2682 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2691 for (i = 0; i < blob->cbData; i++)
2693 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2702 SetLastError(CRYPT_E_ASN1_BADTAG);
2708 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2709 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2710 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2718 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2719 lpszStructType, pbEncoded, cbEncoded,
2720 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2723 *pcbStructInfo = bytesNeeded;
2724 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2725 pvStructInfo, pcbStructInfo, bytesNeeded)))
2727 CRYPT_INTEGER_BLOB *blob;
2729 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2730 pvStructInfo = *(BYTE **)pvStructInfo;
2731 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2732 blob->pbData = (BYTE *)pvStructInfo +
2733 sizeof(CRYPT_INTEGER_BLOB);
2734 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2735 lpszStructType, pbEncoded, cbEncoded,
2736 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2743 SetLastError(STATUS_ACCESS_VIOLATION);
2750 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
2751 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2752 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2758 *pcbStructInfo = sizeof(int);
2763 if (pbEncoded[0] == ASN_ENUMERATED)
2765 unsigned int val = 0, i;
2769 SetLastError(CRYPT_E_ASN1_EOD);
2772 else if (pbEncoded[1] == 0)
2774 SetLastError(CRYPT_E_ASN1_CORRUPT);
2779 /* A little strange looking, but we have to accept a sign byte:
2780 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
2781 * assuming a small length is okay here, it has to be in short
2784 if (pbEncoded[1] > sizeof(unsigned int) + 1)
2786 SetLastError(CRYPT_E_ASN1_LARGE);
2789 for (i = 0; i < pbEncoded[1]; i++)
2792 val |= pbEncoded[2 + i];
2794 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2795 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
2797 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2798 pvStructInfo = *(BYTE **)pvStructInfo;
2799 memcpy(pvStructInfo, &val, sizeof(unsigned int));
2805 SetLastError(CRYPT_E_ASN1_BADTAG);
2811 SetLastError(STATUS_ACCESS_VIOLATION);
2818 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
2821 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
2826 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
2828 if (!isdigit(*(pbEncoded))) \
2830 SetLastError(CRYPT_E_ASN1_CORRUPT); \
2836 (word) += *(pbEncoded)++ - '0'; \
2841 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
2842 SYSTEMTIME *sysTime)
2849 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
2851 WORD hours, minutes = 0;
2852 BYTE sign = *pbEncoded++;
2855 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
2856 if (ret && hours >= 24)
2858 SetLastError(CRYPT_E_ASN1_CORRUPT);
2863 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
2864 if (ret && minutes >= 60)
2866 SetLastError(CRYPT_E_ASN1_CORRUPT);
2874 sysTime->wHour += hours;
2875 sysTime->wMinute += minutes;
2879 if (hours > sysTime->wHour)
2882 sysTime->wHour = 24 - (hours - sysTime->wHour);
2885 sysTime->wHour -= hours;
2886 if (minutes > sysTime->wMinute)
2889 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
2892 sysTime->wMinute -= minutes;
2899 SetLastError(STATUS_ACCESS_VIOLATION);
2906 #define MIN_ENCODED_TIME_LENGTH 10
2908 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
2909 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2910 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2916 *pcbStructInfo = sizeof(FILETIME);
2922 if (pbEncoded[0] == ASN_UTCTIME)
2926 SetLastError(CRYPT_E_ASN1_EOD);
2929 else if (pbEncoded[1] > 0x7f)
2931 /* long-form date strings really can't be valid */
2932 SetLastError(CRYPT_E_ASN1_CORRUPT);
2937 SYSTEMTIME sysTime = { 0 };
2938 BYTE len = pbEncoded[1];
2940 if (len < MIN_ENCODED_TIME_LENGTH)
2942 SetLastError(CRYPT_E_ASN1_CORRUPT);
2948 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
2949 if (sysTime.wYear >= 50)
2950 sysTime.wYear += 1900;
2952 sysTime.wYear += 2000;
2953 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2954 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2955 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2956 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
2959 if (len >= 2 && isdigit(*pbEncoded) &&
2960 isdigit(*(pbEncoded + 1)))
2961 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2963 else if (isdigit(*pbEncoded))
2964 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
2967 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2970 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2971 pDecodePara, pvStructInfo, pcbStructInfo,
2974 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2975 pvStructInfo = *(BYTE **)pvStructInfo;
2976 ret = SystemTimeToFileTime(&sysTime,
2977 (FILETIME *)pvStructInfo);
2984 SetLastError(CRYPT_E_ASN1_BADTAG);
2990 SetLastError(STATUS_ACCESS_VIOLATION);
2997 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
2998 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2999 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3005 *pcbStructInfo = sizeof(FILETIME);
3011 if (pbEncoded[0] == ASN_GENERALTIME)
3015 SetLastError(CRYPT_E_ASN1_EOD);
3018 else if (pbEncoded[1] > 0x7f)
3020 /* long-form date strings really can't be valid */
3021 SetLastError(CRYPT_E_ASN1_CORRUPT);
3026 BYTE len = pbEncoded[1];
3028 if (len < MIN_ENCODED_TIME_LENGTH)
3030 SetLastError(CRYPT_E_ASN1_CORRUPT);
3035 SYSTEMTIME sysTime = { 0 };
3038 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3039 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3040 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3041 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3044 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3047 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3049 if (ret && len > 0 && (*pbEncoded == '.' ||
3056 /* workaround macro weirdness */
3057 digits = min(len, 3);
3058 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3059 sysTime.wMilliseconds);
3062 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3065 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3066 pDecodePara, pvStructInfo, pcbStructInfo,
3069 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3070 pvStructInfo = *(BYTE **)pvStructInfo;
3071 ret = SystemTimeToFileTime(&sysTime,
3072 (FILETIME *)pvStructInfo);
3079 SetLastError(CRYPT_E_ASN1_BADTAG);
3085 SetLastError(STATUS_ACCESS_VIOLATION);
3092 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3093 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3094 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3100 if (pbEncoded[0] == ASN_UTCTIME)
3101 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3102 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3104 else if (pbEncoded[0] == ASN_GENERALTIME)
3105 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3106 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3107 pvStructInfo, pcbStructInfo);
3110 SetLastError(CRYPT_E_ASN1_BADTAG);
3116 SetLastError(STATUS_ACCESS_VIOLATION);
3123 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3124 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3125 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3131 if (pbEncoded[0] == ASN_SEQUENCEOF)
3133 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3135 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3140 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3141 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3143 ptr = pbEncoded + 1 + lenBytes;
3144 remainingLen = dataLen;
3145 while (ret && remainingLen)
3149 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3152 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3154 remainingLen -= 1 + nextLenBytes + nextLen;
3155 ptr += 1 + nextLenBytes + nextLen;
3156 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3157 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3158 bytesNeeded += 1 + nextLenBytes + nextLen;
3164 CRYPT_SEQUENCE_OF_ANY *seq;
3168 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3169 pvStructInfo, pcbStructInfo, bytesNeeded)))
3171 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3172 pvStructInfo = *(BYTE **)pvStructInfo;
3173 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3174 seq->cValue = cValue;
3175 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3177 nextPtr = (BYTE *)seq->rgValue +
3178 cValue * sizeof(CRYPT_DER_BLOB);
3179 ptr = pbEncoded + 1 + lenBytes;
3180 remainingLen = dataLen;
3182 while (ret && remainingLen)
3186 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3189 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3191 seq->rgValue[i].cbData = 1 + nextLenBytes +
3193 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3194 seq->rgValue[i].pbData = (BYTE *)ptr;
3197 seq->rgValue[i].pbData = nextPtr;
3198 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3200 nextPtr += 1 + nextLenBytes + nextLen;
3202 remainingLen -= 1 + nextLenBytes + nextLen;
3203 ptr += 1 + nextLenBytes + nextLen;
3213 SetLastError(CRYPT_E_ASN1_BADTAG);
3219 SetLastError(STATUS_ACCESS_VIOLATION);
3226 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3227 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3228 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3232 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3234 DWORD bytesNeeded, dataLen;
3236 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3238 struct AsnArrayDescriptor arrayDesc = {
3239 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3240 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3241 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3242 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3248 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3249 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3250 0, NULL, NULL, &nameLen, NULL);
3251 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3254 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3256 *pcbStructInfo = bytesNeeded;
3257 else if (*pcbStructInfo < bytesNeeded)
3259 *pcbStructInfo = bytesNeeded;
3260 SetLastError(ERROR_MORE_DATA);
3265 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3269 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3270 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3271 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3272 0, NULL, &name->u.FullName, pcbStructInfo,
3273 name->u.FullName.rgAltEntry);
3276 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3282 SetLastError(CRYPT_E_ASN1_BADTAG);
3288 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3289 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3290 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3292 struct AsnDecodeSequenceItem items[] = {
3293 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3294 DistPointName), CRYPT_AsnDecodeDistPointName,
3295 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3296 DistPointName.u.FullName.rgAltEntry), 0 },
3297 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3298 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3299 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3300 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3301 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3302 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3306 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3307 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3308 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3312 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3313 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3314 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3318 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3319 pDecodePara, pvStructInfo, *pcbStructInfo);
3323 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3324 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3325 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3327 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3328 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3332 SetLastError(STATUS_ACCESS_VIOLATION);
3339 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3340 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3341 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3345 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3346 pDecodePara, pvStructInfo, *pcbStructInfo);
3350 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3351 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3353 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3354 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3358 SetLastError(STATUS_ACCESS_VIOLATION);
3365 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3366 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3367 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3371 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3372 pDecodePara, pvStructInfo, *pcbStructInfo);
3376 struct AsnDecodeSequenceItem items[] = {
3377 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3378 DistPointName), CRYPT_AsnDecodeDistPointName,
3379 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3380 offsetof(CRL_ISSUING_DIST_POINT,
3381 DistPointName.u.FullName.rgAltEntry), 0 },
3382 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3383 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3385 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3386 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3388 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3389 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3390 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3391 OnlySomeReasonFlags.pbData), 0 },
3392 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3393 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3396 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3397 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3398 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3402 SetLastError(STATUS_ACCESS_VIOLATION);
3409 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3410 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3411 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3413 static HCRYPTOIDFUNCSET set = NULL;
3415 CryptDecodeObjectExFunc decodeFunc = NULL;
3416 HCRYPTOIDFUNCADDR hFunc = NULL;
3418 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
3419 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
3420 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3422 if (!pvStructInfo && !pcbStructInfo)
3424 SetLastError(ERROR_INVALID_PARAMETER);
3427 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3428 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3430 SetLastError(ERROR_FILE_NOT_FOUND);
3435 SetLastError(CRYPT_E_ASN1_EOD);
3438 if (cbEncoded > MAX_ENCODED_LEN)
3440 SetLastError(CRYPT_E_ASN1_LARGE);
3444 SetLastError(NOERROR);
3445 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3446 *(BYTE **)pvStructInfo = NULL;
3447 if (!HIWORD(lpszStructType))
3449 switch (LOWORD(lpszStructType))
3451 case (WORD)X509_CERT:
3452 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3454 case (WORD)X509_CERT_TO_BE_SIGNED:
3455 decodeFunc = CRYPT_AsnDecodeCert;
3457 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3458 decodeFunc = CRYPT_AsnDecodeCRL;
3460 case (WORD)X509_EXTENSIONS:
3461 decodeFunc = CRYPT_AsnDecodeExtensions;
3463 case (WORD)X509_NAME_VALUE:
3464 decodeFunc = CRYPT_AsnDecodeNameValue;
3466 case (WORD)X509_NAME:
3467 decodeFunc = CRYPT_AsnDecodeName;
3469 case (WORD)X509_PUBLIC_KEY_INFO:
3470 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
3472 case (WORD)X509_ALTERNATE_NAME:
3473 decodeFunc = CRYPT_AsnDecodeAltName;
3475 case (WORD)X509_BASIC_CONSTRAINTS:
3476 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3478 case (WORD)X509_BASIC_CONSTRAINTS2:
3479 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3481 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3482 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3484 case (WORD)X509_UNICODE_NAME:
3485 decodeFunc = CRYPT_AsnDecodeUnicodeName;
3487 case (WORD)X509_UNICODE_NAME_VALUE:
3488 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
3490 case (WORD)X509_OCTET_STRING:
3491 decodeFunc = CRYPT_AsnDecodeOctets;
3493 case (WORD)X509_BITS:
3494 case (WORD)X509_KEY_USAGE:
3495 decodeFunc = CRYPT_AsnDecodeBits;
3497 case (WORD)X509_INTEGER:
3498 decodeFunc = CRYPT_AsnDecodeInt;
3500 case (WORD)X509_MULTI_BYTE_INTEGER:
3501 decodeFunc = CRYPT_AsnDecodeInteger;
3503 case (WORD)X509_MULTI_BYTE_UINT:
3504 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3506 case (WORD)X509_ENUMERATED:
3507 decodeFunc = CRYPT_AsnDecodeEnumerated;
3509 case (WORD)X509_CHOICE_OF_TIME:
3510 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3512 case (WORD)X509_SEQUENCE_OF_ANY:
3513 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3515 case (WORD)PKCS_UTC_TIME:
3516 decodeFunc = CRYPT_AsnDecodeUtcTime;
3518 case (WORD)X509_CRL_DIST_POINTS:
3519 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3521 case (WORD)X509_ENHANCED_KEY_USAGE:
3522 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3524 case (WORD)X509_ISSUING_DIST_POINT:
3525 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3528 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3531 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3532 decodeFunc = CRYPT_AsnDecodeExtensions;
3533 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3534 decodeFunc = CRYPT_AsnDecodeUtcTime;
3535 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3536 decodeFunc = CRYPT_AsnDecodeEnumerated;
3537 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3538 decodeFunc = CRYPT_AsnDecodeBits;
3539 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3540 decodeFunc = CRYPT_AsnDecodeOctets;
3541 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3542 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3543 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3544 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3545 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3546 decodeFunc = CRYPT_AsnDecodeAltName;
3547 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3548 decodeFunc = CRYPT_AsnDecodeAltName;
3549 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3550 decodeFunc = CRYPT_AsnDecodeAltName;
3551 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3552 decodeFunc = CRYPT_AsnDecodeAltName;
3553 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3554 decodeFunc = CRYPT_AsnDecodeAltName;
3555 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3556 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3557 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3558 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3559 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3560 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3562 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3563 debugstr_a(lpszStructType));
3567 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
3568 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3569 (void **)&decodeFunc, &hFunc);
3572 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3573 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3575 SetLastError(ERROR_FILE_NOT_FOUND);
3577 CryptFreeOIDFunctionAddress(hFunc, 0);