2 * Copyright 2005 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface is
21 * undocumented, so I implement them here.
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
39 #define NONAMELESSUNION
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "crypt32_private.h"
51 /* This is a bit arbitrary, but to set some limit: */
52 #define MAX_ENCODED_LEN 0x02000000
54 #define ASN_FLAGS_MASK 0xe0
55 #define ASN_TYPE_MASK 0x1f
57 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
65 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
66 DWORD, DWORD, void *, DWORD *);
67 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
68 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
70 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
71 * The dwCertEncodingType and lpszStructType are ignored by the built-in
72 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
73 * since it must call functions in external DLLs that follow these signatures.
75 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
77 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
78 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
80 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
81 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
82 * time, doesn't do memory allocation, and doesn't do exception handling.
83 * (This isn't intended to be the externally-called one.)
85 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
86 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
87 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
88 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
89 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
90 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
91 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
92 /* Internal function */
93 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
94 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
95 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
96 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
97 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
98 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
99 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
100 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
101 * member has been initialized, doesn't do exception handling, and doesn't do
104 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
105 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
106 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
107 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
108 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
109 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
110 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
111 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
112 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
113 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
114 * member has been initialized, doesn't do exception handling, and doesn't do
117 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
118 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
119 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
120 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
121 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
122 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
123 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
124 void *pvStructInfo, DWORD *pcbStructInfo);
126 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
127 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
128 DWORD *pcbStructInfo)
130 static HCRYPTOIDFUNCSET set = NULL;
132 CryptDecodeObjectFunc pCryptDecodeObject;
133 HCRYPTOIDFUNCADDR hFunc;
135 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType,
136 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
137 pvStructInfo, pcbStructInfo);
139 if (!pvStructInfo && !pcbStructInfo)
141 SetLastError(ERROR_INVALID_PARAMETER);
145 /* Try registered DLL first.. */
147 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
148 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
149 (void **)&pCryptDecodeObject, &hFunc);
150 if (pCryptDecodeObject)
152 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
153 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
154 CryptFreeOIDFunctionAddress(hFunc, 0);
158 /* If not, use CryptDecodeObjectEx */
159 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
160 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
165 /* Gets the number of length bytes from the given (leading) length byte */
166 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
168 /* Helper function to get the encoded length of the data starting at pbEncoded,
169 * where pbEncoded[0] is the tag. If the data are too short to contain a
170 * length or if the length is too large for cbEncoded, sets an appropriate
171 * error code and returns FALSE.
173 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
180 SetLastError(CRYPT_E_ASN1_CORRUPT);
183 else if (pbEncoded[1] <= 0x7f)
185 if (pbEncoded[1] + 1 > cbEncoded)
187 SetLastError(CRYPT_E_ASN1_EOD);
198 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
200 if (lenLen > sizeof(DWORD) + 1)
202 SetLastError(CRYPT_E_ASN1_LARGE);
205 else if (lenLen + 2 > cbEncoded)
207 SetLastError(CRYPT_E_ASN1_CORRUPT);
220 if (out + lenLen + 1 > cbEncoded)
222 SetLastError(CRYPT_E_ASN1_EOD);
235 /* Helper function to check *pcbStructInfo, set it to the required size, and
236 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
237 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
238 * pointer to the newly allocated memory.
240 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
241 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
246 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
248 if (pDecodePara && pDecodePara->pfnAlloc)
249 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
251 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
252 if (!*(BYTE **)pvStructInfo)
255 *pcbStructInfo = bytesNeeded;
257 else if (*pcbStructInfo < bytesNeeded)
259 *pcbStructInfo = bytesNeeded;
260 SetLastError(ERROR_MORE_DATA);
267 * The expected tag of the item. If tag is 0, decodeFunc is called
268 * regardless of the tag value seen.
270 * A sequence is decoded into a struct. The offset member is the
271 * offset of this item within that struct.
273 * The decoder function to use. If this is NULL, then the member isn't
274 * decoded, but minSize space is reserved for it.
276 * The minimum amount of space occupied after decoding. You must set this.
278 * If true, and the tag doesn't match the expected tag for this item,
279 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
280 * filled with 0 for this member.
281 * hasPointer, pointerOffset, minSize:
282 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
283 * the offset within the (outer) struct of the data pointer (or to the
284 * first data pointer, if more than one exist).
286 * Used by CRYPT_AsnDecodeSequence, not for your use.
288 struct AsnDecodeSequenceItem
292 CryptDecodeObjectExFunc decodeFunc;
300 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
301 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
302 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData)
308 ptr = pbEncoded + 1 + GET_LEN_BYTES(pbEncoded[1]);
309 for (i = 0, ret = TRUE; ret && i < cItem; i++)
311 if (cbEncoded - (ptr - pbEncoded) != 0)
315 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
318 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
320 if (ptr[0] == items[i].tag || !items[i].tag)
322 if (nextData && pvStructInfo && items[i].hasPointer)
324 TRACE("Setting next pointer to %p\n",
326 *(BYTE **)((BYTE *)pvStructInfo +
327 items[i].pointerOffset) = nextData;
329 if (items[i].decodeFunc)
332 TRACE("decoding item %ld\n", i);
334 TRACE("sizing item %ld\n", i);
335 ret = items[i].decodeFunc(dwCertEncodingType,
336 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
337 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
338 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
339 : NULL, &items[i].size);
342 if (nextData && items[i].hasPointer &&
343 items[i].size > items[i].minSize)
345 nextData += items[i].size - items[i].minSize;
346 /* align nextData to DWORD boundaries */
347 if (items[i].size % sizeof(DWORD))
348 nextData += sizeof(DWORD) - items[i].size %
351 /* Account for alignment padding */
352 if (items[i].size % sizeof(DWORD))
353 items[i].size += sizeof(DWORD) -
354 items[i].size % sizeof(DWORD);
355 ptr += 1 + nextItemLenBytes + nextItemLen;
357 else if (items[i].optional &&
358 GetLastError() == CRYPT_E_ASN1_BADTAG)
360 TRACE("skipping optional item %ld\n", i);
361 items[i].size = items[i].minSize;
362 SetLastError(NOERROR);
366 TRACE("item %ld failed: %08lx\n", i,
370 items[i].size = items[i].minSize;
372 else if (items[i].optional)
374 TRACE("skipping optional item %ld\n", i);
375 items[i].size = items[i].minSize;
379 TRACE("tag %02x doesn't match expected %02x\n",
380 ptr[0], items[i].tag);
381 SetLastError(CRYPT_E_ASN1_BADTAG);
386 else if (items[i].optional)
388 TRACE("missing optional item %ld, skipping\n", i);
389 items[i].size = items[i].minSize;
393 TRACE("not enough bytes for item %ld, failing\n", i);
394 SetLastError(CRYPT_E_ASN1_CORRUPT);
398 if (cbEncoded - (ptr - pbEncoded) != 0)
400 TRACE("%ld remaining bytes, failing\n", cbEncoded -
402 SetLastError(CRYPT_E_ASN1_CORRUPT);
408 /* This decodes an arbitrary sequence into a contiguous block of memory
409 * (basically, a struct.) Each element being decoded is described by a struct
410 * AsnDecodeSequenceItem, see above.
411 * startingPointer is an optional pointer to the first place where dynamic
412 * data will be stored. If you know the starting offset, you may pass it
413 * here. Otherwise, pass NULL, and one will be inferred from the items.
414 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
415 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
417 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
418 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
419 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
420 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
424 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded,
425 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
428 if (pbEncoded[0] == ASN_SEQUENCE)
432 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
436 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
437 cbEncoded, dwFlags, NULL, NULL);
440 DWORD bytesNeeded = 0, structSize = 0;
442 for (i = 0; i < cItem; i++)
444 bytesNeeded += items[i].size;
445 structSize += items[i].minSize;
448 *pcbStructInfo = bytesNeeded;
449 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
450 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
454 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
455 pvStructInfo = *(BYTE **)pvStructInfo;
457 nextData = (BYTE *)startingPointer;
459 nextData = (BYTE *)pvStructInfo + structSize;
460 memset(pvStructInfo, 0, structSize);
461 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
462 pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
469 SetLastError(CRYPT_E_ASN1_BADTAG);
472 TRACE("returning %d (%08lx)\n", ret, GetLastError());
477 * The expected tag of the entire encoded array (usually a variant
478 * of ASN_SETOF or ASN_SEQUENCEOF.)
480 * used to decode each item in the array
482 * is the minimum size of each decoded item
484 * indicates whether each item has a dynamic pointer
486 * indicates the offset within itemSize at which the pointer exists
488 struct AsnArrayDescriptor
491 CryptDecodeObjectExFunc decodeFunc;
497 struct AsnArrayItemSize
503 /* Decodes an array of like types into a struct GenericArray.
504 * The layout and decoding of the array are described by a struct
505 * AsnArrayDescriptor.
507 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
508 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
509 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
510 void *startingPointer)
514 TRACE("%p, %p, %ld, %08lx, %p, %p, %ld, %p\n", arrayDesc, pbEncoded,
515 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
518 if (pbEncoded[0] == arrayDesc->tag)
522 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
524 DWORD bytesNeeded, cItems = 0;
525 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
526 /* There can be arbitrarily many items, but there is often only one.
528 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
530 bytesNeeded = sizeof(struct GenericArray);
535 for (ptr = pbEncoded + 1 + lenBytes; ret &&
536 ptr - pbEncoded - 1 - lenBytes < dataLen; )
538 DWORD itemLenBytes, itemDataLen, size;
540 itemLenBytes = GET_LEN_BYTES(ptr[1]);
541 /* Each item decoded may not tolerate extraneous bytes, so
542 * get the length of the next element and pass it directly.
544 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
547 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
548 1 + itemLenBytes + itemDataLen,
549 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
556 if (itemSizes != &itemSize)
557 itemSizes = CryptMemRealloc(itemSizes,
558 cItems * sizeof(struct AsnArrayItemSize));
563 cItems * sizeof(struct AsnArrayItemSize));
564 memcpy(itemSizes, &itemSize, sizeof(itemSize));
568 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
570 itemSizes[cItems - 1].size = size;
572 ret = CRYPT_GetLen(ptr,
573 cbEncoded - (ptr - pbEncoded), &nextLen);
575 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
585 *pcbStructInfo = bytesNeeded;
586 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
587 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
592 struct GenericArray *array;
594 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
595 pvStructInfo = *(BYTE **)pvStructInfo;
596 array = (struct GenericArray *)pvStructInfo;
597 array->cItems = cItems;
599 array->rgItems = startingPointer;
601 array->rgItems = (BYTE *)array +
602 sizeof(struct GenericArray);
603 nextData = (BYTE *)array->rgItems +
604 array->cItems * arrayDesc->itemSize;
605 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
606 i < cItems && ptr - pbEncoded - 1 - lenBytes <
609 if (arrayDesc->hasPointer)
610 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
611 + arrayDesc->pointerOffset) = nextData;
612 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
613 itemSizes[i].encodedLen,
614 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
615 array->rgItems + i * arrayDesc->itemSize,
621 nextData += itemSizes[i].size - arrayDesc->itemSize;
622 ret = CRYPT_GetLen(ptr,
623 cbEncoded - (ptr - pbEncoded), &nextLen);
625 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
630 if (itemSizes != &itemSize)
631 CryptMemFree(itemSizes);
636 SetLastError(CRYPT_E_ASN1_BADTAG);
642 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
643 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
644 * to CRYPT_E_ASN1_CORRUPT.
645 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
648 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
649 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
650 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
655 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
657 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
658 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
660 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
661 bytesNeeded += 1 + lenBytes + dataLen;
664 *pcbStructInfo = bytesNeeded;
665 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
666 pvStructInfo, pcbStructInfo, bytesNeeded)))
668 CRYPT_DER_BLOB *blob;
670 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
671 pvStructInfo = *(BYTE **)pvStructInfo;
672 blob = (CRYPT_DER_BLOB *)pvStructInfo;
673 blob->cbData = 1 + lenBytes + dataLen;
676 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
677 blob->pbData = (BYTE *)pbEncoded;
680 assert(blob->pbData);
681 memcpy(blob->pbData, pbEncoded, blob->cbData);
686 SetLastError(CRYPT_E_ASN1_CORRUPT);
694 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
695 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
696 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
697 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
701 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
702 pDecodePara, pvStructInfo, *pcbStructInfo);
704 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
707 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
708 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
709 pvStructInfo, pcbStructInfo);
710 if (ret && pvStructInfo)
712 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
719 for (i = 0; i < blob->cbData / 2; i++)
721 temp = blob->pbData[i];
722 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
723 blob->pbData[blob->cbData - i - 1] = temp;
727 TRACE("returning %d (%08lx)\n", ret, GetLastError());
731 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
732 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
733 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
737 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
738 pDecodePara, pvStructInfo, *pcbStructInfo);
742 struct AsnDecodeSequenceItem items[] = {
743 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
744 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
745 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
746 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
747 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
748 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
749 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
750 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
751 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
752 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
755 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
756 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
757 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
758 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
759 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
763 SetLastError(STATUS_ACCESS_VIOLATION);
770 /* Internal function */
771 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
772 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
773 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
778 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
780 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
782 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
783 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
784 pvStructInfo, pcbStructInfo);
789 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
790 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
791 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
795 struct AsnDecodeSequenceItem items[] = {
796 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
797 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
798 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
799 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
802 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
803 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
804 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
808 /* Internal function */
809 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
810 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
811 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
816 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
818 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
820 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
821 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
822 pDecodePara, pvStructInfo, pcbStructInfo);
827 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
828 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
829 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
833 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
834 pDecodePara, pvStructInfo, *pcbStructInfo);
838 struct AsnDecodeSequenceItem items[] = {
839 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
840 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
841 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
842 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
843 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
844 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
845 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
846 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
847 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
848 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
850 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
851 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
853 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
854 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
856 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
857 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
858 FALSE, TRUE, offsetof(CERT_INFO,
859 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
860 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
861 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
862 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
863 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
864 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
865 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
866 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
867 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
868 offsetof(CERT_INFO, rgExtension), 0 },
871 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
872 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
873 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
877 SetLastError(STATUS_ACCESS_VIOLATION);
884 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
885 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
886 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
889 struct AsnDecodeSequenceItem items[] = {
890 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
891 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
892 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
893 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
894 sizeof(FILETIME), FALSE, FALSE, 0 },
895 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
896 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
897 offsetof(CRL_ENTRY, rgExtension), 0 },
899 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
901 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
904 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
905 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
906 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
910 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
911 * been set prior to calling.
913 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
914 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
915 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
918 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
919 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
920 offsetof(CRL_ENTRY, SerialNumber.pbData) };
921 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
923 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
924 pDecodePara, pvStructInfo, *pcbStructInfo);
926 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
927 pDecodePara, pvStructInfo, pcbStructInfo,
928 entries ? entries->rgItems : NULL);
929 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
933 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
934 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
935 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
939 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
940 pDecodePara, pvStructInfo, *pcbStructInfo);
944 struct AsnDecodeSequenceItem items[] = {
945 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CRL_INFO, dwVersion),
946 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
947 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
948 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
949 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
950 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
951 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
953 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
954 sizeof(FILETIME), FALSE, FALSE, 0 },
955 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
956 sizeof(FILETIME), TRUE, FALSE, 0 },
957 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
958 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
959 offsetof(CRL_INFO, rgCRLEntry), 0 },
960 /* Note that the extensions are ignored by MS, so I'll ignore them too
962 { 0, offsetof(CRL_INFO, cExtension), NULL,
963 sizeof(CERT_EXTENSIONS), TRUE, FALSE, 0 },
966 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
967 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
968 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
972 SetLastError(STATUS_ACCESS_VIOLATION);
977 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
981 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
982 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
983 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
987 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
988 pDecodePara, pvStructInfo, *pcbStructInfo);
990 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
994 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
996 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
997 DWORD bytesNeeded = sizeof(LPSTR);
1001 /* The largest possible string for the first two components
1002 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1007 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1008 pbEncoded[1 + lenBytes] / 40,
1009 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1011 bytesNeeded += strlen(firstTwo) + 1;
1012 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1013 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1015 /* large enough for ".4000000" */
1019 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1026 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1029 SetLastError(CRYPT_E_ASN1_CORRUPT);
1036 snprintf(str, sizeof(str), ".%d", val);
1037 bytesNeeded += strlen(str);
1042 *pcbStructInfo = bytesNeeded;
1043 else if (*pcbStructInfo < bytesNeeded)
1045 *pcbStructInfo = bytesNeeded;
1046 SetLastError(ERROR_MORE_DATA);
1054 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1057 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1058 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1060 pszObjId += strlen(pszObjId);
1061 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1062 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1066 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1075 sprintf(pszObjId, ".%d", val);
1076 pszObjId += strlen(pszObjId);
1080 *(LPSTR *)pvStructInfo = NULL;
1081 *pcbStructInfo = bytesNeeded;
1088 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1091 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1092 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1093 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1095 struct AsnDecodeSequenceItem items[] = {
1096 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1097 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1098 offsetof(CERT_EXTENSION, pszObjId), 0 },
1099 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1100 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1101 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1102 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1103 offsetof(CERT_EXTENSION, Value.pbData) },
1106 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1108 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
1112 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1113 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1114 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1115 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1117 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1118 debugstr_a(ext->pszObjId));
1119 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1123 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1124 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1125 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1128 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1129 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1130 offsetof(CERT_EXTENSION, pszObjId) };
1131 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1133 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1134 pDecodePara, pvStructInfo, *pcbStructInfo);
1136 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1137 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1141 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1142 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1143 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1149 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1150 lpszStructType, pbEncoded, cbEncoded,
1151 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1152 if (ret && pvStructInfo)
1154 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1155 pcbStructInfo, *pcbStructInfo);
1158 CERT_EXTENSIONS *exts;
1160 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1161 pvStructInfo = *(BYTE **)pvStructInfo;
1162 exts = (CERT_EXTENSIONS *)pvStructInfo;
1163 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1164 sizeof(CERT_EXTENSIONS));
1165 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1166 lpszStructType, pbEncoded, cbEncoded,
1167 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1174 SetLastError(STATUS_ACCESS_VIOLATION);
1181 /* Warning: this assumes the address of value->Value.pbData is already set, in
1182 * order to avoid overwriting memory. (In some cases, it may change it, if it
1183 * doesn't copy anything to memory.) Be sure to set it correctly!
1185 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1186 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1187 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1191 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1193 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1195 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1197 switch (pbEncoded[0])
1199 case ASN_NUMERICSTRING:
1200 case ASN_PRINTABLESTRING:
1205 FIXME("Unimplemented string type %02x\n", pbEncoded[0]);
1206 SetLastError(OSS_UNIMPLEMENTED);
1211 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE);
1213 switch (pbEncoded[0])
1215 case ASN_NUMERICSTRING:
1216 case ASN_PRINTABLESTRING:
1219 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1220 bytesNeeded += dataLen;
1224 *pcbStructInfo = bytesNeeded;
1225 else if (*pcbStructInfo < bytesNeeded)
1227 *pcbStructInfo = bytesNeeded;
1228 SetLastError(ERROR_MORE_DATA);
1233 *pcbStructInfo = bytesNeeded;
1234 switch (pbEncoded[0])
1236 case ASN_NUMERICSTRING:
1237 value->dwValueType = CERT_RDN_NUMERIC_STRING;
1239 case ASN_PRINTABLESTRING:
1240 value->dwValueType = CERT_RDN_PRINTABLE_STRING;
1243 value->dwValueType = CERT_RDN_IA5_STRING;
1246 value->dwValueType = CERT_RDN_T61_STRING;
1251 switch (pbEncoded[0])
1253 case ASN_NUMERICSTRING:
1254 case ASN_PRINTABLESTRING:
1257 value->Value.cbData = dataLen;
1258 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1259 value->Value.pbData = (BYTE *)pbEncoded + 1 +
1263 assert(value->Value.pbData);
1264 memcpy(value->Value.pbData,
1265 pbEncoded + 1 + lenBytes, dataLen);
1272 value->Value.cbData = 0;
1273 value->Value.pbData = NULL;
1281 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1282 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1283 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1289 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1290 lpszStructType, pbEncoded, cbEncoded,
1291 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1292 if (ret && pvStructInfo)
1294 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1295 pcbStructInfo, *pcbStructInfo);
1298 CERT_NAME_VALUE *value;
1300 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1301 pvStructInfo = *(BYTE **)pvStructInfo;
1302 value = (CERT_NAME_VALUE *)pvStructInfo;
1303 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1304 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1305 lpszStructType, pbEncoded, cbEncoded,
1306 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1313 SetLastError(STATUS_ACCESS_VIOLATION);
1320 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1321 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1322 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1325 struct AsnDecodeSequenceItem items[] = {
1326 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1327 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1328 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1329 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1330 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1331 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1333 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1335 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1336 pvStructInfo, *pcbStructInfo);
1339 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1340 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1341 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1342 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1345 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1346 debugstr_a(attr->pszObjId));
1347 TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1349 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1353 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1354 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1355 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1358 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1359 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1360 offsetof(CERT_RDN_ATTR, pszObjId) };
1361 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1363 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1364 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1368 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1369 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1370 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1376 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1377 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1378 offsetof(CERT_RDN, rgRDNAttr) };
1380 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1381 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1385 SetLastError(STATUS_ACCESS_VIOLATION);
1392 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1393 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1394 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1397 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1399 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1400 pDecodePara, pvStructInfo, *pcbStructInfo);
1402 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1403 bytesNeeded += cbEncoded;
1405 *pcbStructInfo = bytesNeeded;
1406 else if (*pcbStructInfo < bytesNeeded)
1408 SetLastError(ERROR_MORE_DATA);
1409 *pcbStructInfo = bytesNeeded;
1414 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1416 *pcbStructInfo = bytesNeeded;
1417 blob->cbData = cbEncoded;
1418 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1419 blob->pbData = (LPBYTE)pbEncoded;
1422 assert(blob->pbData);
1423 memcpy(blob->pbData, pbEncoded, blob->cbData);
1429 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1430 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1431 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1433 CRYPT_ALGORITHM_IDENTIFIER *algo =
1434 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1436 struct AsnDecodeSequenceItem items[] = {
1437 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1438 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1439 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1440 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1441 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1442 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1445 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1446 pDecodePara, pvStructInfo, *pcbStructInfo);
1448 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1449 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1450 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1451 if (ret && pvStructInfo)
1453 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1454 debugstr_a(algo->pszObjId));
1459 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1460 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1461 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1464 struct AsnDecodeSequenceItem items[] = {
1465 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1466 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1467 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1468 Algorithm.pszObjId) },
1469 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1470 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1471 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1473 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1475 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1476 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1477 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1478 info->Algorithm.Parameters.pbData : NULL);
1482 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1483 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1484 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1492 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1493 lpszStructType, pbEncoded, cbEncoded,
1494 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1497 *pcbStructInfo = bytesNeeded;
1498 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1499 pvStructInfo, pcbStructInfo, bytesNeeded)))
1501 PCERT_PUBLIC_KEY_INFO info;
1503 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1504 pvStructInfo = *(BYTE **)pvStructInfo;
1505 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1506 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
1507 sizeof(CERT_PUBLIC_KEY_INFO);
1508 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1509 lpszStructType, pbEncoded, cbEncoded,
1510 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1517 SetLastError(STATUS_ACCESS_VIOLATION);
1524 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
1525 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1526 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1532 SetLastError(CRYPT_E_ASN1_CORRUPT);
1535 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
1537 SetLastError(CRYPT_E_ASN1_CORRUPT);
1540 if (pbEncoded[1] > 1)
1542 SetLastError(CRYPT_E_ASN1_CORRUPT);
1547 *pcbStructInfo = sizeof(BOOL);
1550 else if (*pcbStructInfo < sizeof(BOOL))
1552 *pcbStructInfo = sizeof(BOOL);
1553 SetLastError(ERROR_MORE_DATA);
1558 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
1561 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1565 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
1566 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1567 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1569 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
1570 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
1573 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1574 pDecodePara, pvStructInfo, *pcbStructInfo);
1578 SetLastError(CRYPT_E_ASN1_CORRUPT);
1581 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
1583 SetLastError(CRYPT_E_ASN1_BADTAG);
1586 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1587 if (1 + lenBytes > cbEncoded)
1589 SetLastError(CRYPT_E_ASN1_CORRUPT);
1592 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1594 switch (pbEncoded[0] & ASN_TYPE_MASK)
1596 case 1: /* rfc822Name */
1597 case 2: /* dNSName */
1598 case 6: /* uniformResourceIdentifier */
1599 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1601 case 7: /* iPAddress */
1602 bytesNeeded += dataLen;
1604 case 8: /* registeredID */
1605 /* FIXME: decode as OID */
1606 case 0: /* otherName */
1607 case 4: /* directoryName */
1609 SetLastError(CRYPT_E_ASN1_BADTAG);
1612 case 3: /* x400Address, unimplemented */
1613 case 5: /* ediPartyName, unimplemented */
1614 SetLastError(CRYPT_E_ASN1_BADTAG);
1618 SetLastError(CRYPT_E_ASN1_CORRUPT);
1624 *pcbStructInfo = bytesNeeded;
1625 else if (*pcbStructInfo < bytesNeeded)
1627 *pcbStructInfo = bytesNeeded;
1628 SetLastError(ERROR_MORE_DATA);
1633 *pcbStructInfo = bytesNeeded;
1634 /* MS used values one greater than the asn1 ones.. sigh */
1635 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
1636 switch (pbEncoded[0] & ASN_TYPE_MASK)
1638 case 1: /* rfc822Name */
1639 case 2: /* dNSName */
1640 case 6: /* uniformResourceIdentifier */
1644 for (i = 0; i < dataLen; i++)
1645 entry->u.pwszURL[i] =
1646 (WCHAR)pbEncoded[1 + lenBytes + i];
1647 entry->u.pwszURL[i] = 0;
1648 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
1649 debugstr_w(entry->u.pwszURL));
1652 case 7: /* iPAddress */
1653 /* The next data pointer is in the pwszURL spot, that is,
1654 * the first 4 bytes. Need to move it to the next spot.
1656 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
1657 entry->u.IPAddress.cbData = dataLen;
1658 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
1668 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
1669 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1670 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1673 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1674 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
1675 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
1676 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
1678 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1679 pDecodePara, pvStructInfo, *pcbStructInfo);
1682 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
1683 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1684 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
1688 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
1689 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1690 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1694 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1695 pDecodePara, pvStructInfo, *pcbStructInfo);
1699 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1700 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
1701 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
1703 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1704 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1708 SetLastError(STATUS_ACCESS_VIOLATION);
1715 struct PATH_LEN_CONSTRAINT
1717 BOOL fPathLenConstraint;
1718 DWORD dwPathLenConstraint;
1721 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
1722 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1723 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1727 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1728 pvStructInfo, *pcbStructInfo);
1732 if (pbEncoded[0] == ASN_INTEGER)
1734 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
1737 *pcbStructInfo = bytesNeeded;
1738 else if (*pcbStructInfo < bytesNeeded)
1740 SetLastError(ERROR_MORE_DATA);
1741 *pcbStructInfo = bytesNeeded;
1746 struct PATH_LEN_CONSTRAINT *constraint =
1747 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
1748 DWORD size = sizeof(constraint->dwPathLenConstraint);
1750 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
1751 pbEncoded, cbEncoded, 0, NULL,
1752 &constraint->dwPathLenConstraint, &size);
1754 constraint->fPathLenConstraint = TRUE;
1755 TRACE("got an int, dwPathLenConstraint is %ld\n",
1756 constraint->dwPathLenConstraint);
1761 SetLastError(CRYPT_E_ASN1_CORRUPT);
1765 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1769 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
1770 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1771 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1774 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1775 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
1776 offsetof(CERT_NAME_BLOB, pbData) };
1777 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1779 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1780 pDecodePara, pvStructInfo, *pcbStructInfo);
1782 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1783 pDecodePara, pvStructInfo, pcbStructInfo,
1784 entries ? entries->rgItems : NULL);
1785 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1789 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
1790 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1791 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1797 struct AsnDecodeSequenceItem items[] = {
1798 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
1799 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1800 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
1801 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
1802 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
1803 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
1804 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
1805 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
1806 sizeof(struct GenericArray), TRUE, TRUE,
1807 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
1810 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1811 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1812 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1816 SetLastError(STATUS_ACCESS_VIOLATION);
1823 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
1824 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1825 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1831 struct AsnDecodeSequenceItem items[] = {
1832 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
1833 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
1834 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
1835 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
1836 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
1839 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1840 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1841 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1845 SetLastError(STATUS_ACCESS_VIOLATION);
1852 #define RSA1_MAGIC 0x31415352
1854 struct DECODED_RSA_PUB_KEY
1857 CRYPT_INTEGER_BLOB modulus;
1860 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
1861 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1862 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1868 struct AsnDecodeSequenceItem items[] = {
1869 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
1870 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
1871 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
1873 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
1874 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
1876 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
1879 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1880 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
1881 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
1884 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1885 decodedKey->modulus.cbData;
1889 *pcbStructInfo = bytesNeeded;
1892 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1893 pvStructInfo, pcbStructInfo, bytesNeeded)))
1896 RSAPUBKEY *rsaPubKey;
1898 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1899 pvStructInfo = *(BYTE **)pvStructInfo;
1900 hdr = (BLOBHEADER *)pvStructInfo;
1901 hdr->bType = PUBLICKEYBLOB;
1902 hdr->bVersion = CUR_BLOB_VERSION;
1904 hdr->aiKeyAlg = CALG_RSA_KEYX;
1905 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
1906 sizeof(BLOBHEADER));
1907 rsaPubKey->magic = RSA1_MAGIC;
1908 rsaPubKey->pubexp = decodedKey->pubexp;
1909 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
1910 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
1911 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
1912 decodedKey->modulus.cbData);
1914 LocalFree(decodedKey);
1919 SetLastError(STATUS_ACCESS_VIOLATION);
1926 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
1927 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1928 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1931 DWORD bytesNeeded, dataLen;
1933 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1934 pDecodePara, pvStructInfo, *pcbStructInfo);
1936 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1938 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1939 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
1941 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
1943 *pcbStructInfo = bytesNeeded;
1944 else if (*pcbStructInfo < bytesNeeded)
1946 SetLastError(ERROR_MORE_DATA);
1947 *pcbStructInfo = bytesNeeded;
1952 CRYPT_DATA_BLOB *blob;
1953 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1955 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
1956 blob->cbData = dataLen;
1957 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1958 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
1961 assert(blob->pbData);
1963 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
1971 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
1972 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1973 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1977 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1978 pDecodePara, pvStructInfo, *pcbStructInfo);
1986 SetLastError(CRYPT_E_ASN1_CORRUPT);
1989 else if (pbEncoded[0] != ASN_OCTETSTRING)
1991 SetLastError(CRYPT_E_ASN1_BADTAG);
1994 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
1995 lpszStructType, pbEncoded, cbEncoded,
1996 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1999 *pcbStructInfo = bytesNeeded;
2000 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2001 pvStructInfo, pcbStructInfo, bytesNeeded)))
2003 CRYPT_DATA_BLOB *blob;
2005 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2006 pvStructInfo = *(BYTE **)pvStructInfo;
2007 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2008 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2009 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2010 lpszStructType, pbEncoded, cbEncoded,
2011 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2018 SetLastError(STATUS_ACCESS_VIOLATION);
2025 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2026 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2027 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2031 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2032 pDecodePara, pvStructInfo, *pcbStructInfo);
2034 if (pbEncoded[0] == ASN_BITSTRING)
2036 DWORD bytesNeeded, dataLen;
2038 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2040 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2041 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2043 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2045 *pcbStructInfo = bytesNeeded;
2046 else if (*pcbStructInfo < bytesNeeded)
2048 *pcbStructInfo = bytesNeeded;
2049 SetLastError(ERROR_MORE_DATA);
2054 CRYPT_BIT_BLOB *blob;
2056 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2057 blob->cbData = dataLen - 1;
2058 blob->cUnusedBits = *(pbEncoded + 1 +
2059 GET_LEN_BYTES(pbEncoded[1]));
2060 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2062 blob->pbData = (BYTE *)pbEncoded + 2 +
2063 GET_LEN_BYTES(pbEncoded[1]);
2067 assert(blob->pbData);
2070 BYTE mask = 0xff << blob->cUnusedBits;
2072 memcpy(blob->pbData, pbEncoded + 2 +
2073 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2074 blob->pbData[blob->cbData - 1] &= mask;
2082 SetLastError(CRYPT_E_ASN1_BADTAG);
2085 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2089 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2090 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2091 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2095 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2096 pDecodePara, pvStructInfo, pcbStructInfo);
2102 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2103 lpszStructType, pbEncoded, cbEncoded,
2104 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2107 *pcbStructInfo = bytesNeeded;
2108 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2109 pvStructInfo, pcbStructInfo, bytesNeeded)))
2111 CRYPT_BIT_BLOB *blob;
2113 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2114 pvStructInfo = *(BYTE **)pvStructInfo;
2115 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2116 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2117 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2118 lpszStructType, pbEncoded, cbEncoded,
2119 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2126 SetLastError(STATUS_ACCESS_VIOLATION);
2130 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2134 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2135 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2136 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2142 *pcbStructInfo = sizeof(int);
2147 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2148 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2149 DWORD size = sizeof(buf);
2151 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2152 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2153 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size);
2156 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2157 pvStructInfo, pcbStructInfo, sizeof(int))))
2161 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2162 pvStructInfo = *(BYTE **)pvStructInfo;
2163 if (blob->pbData[blob->cbData - 1] & 0x80)
2165 /* initialize to a negative value to sign-extend */
2170 for (i = 0; i < blob->cbData; i++)
2173 val |= blob->pbData[blob->cbData - i - 1];
2175 memcpy(pvStructInfo, &val, sizeof(int));
2178 else if (GetLastError() == ERROR_MORE_DATA)
2179 SetLastError(CRYPT_E_ASN1_LARGE);
2183 SetLastError(STATUS_ACCESS_VIOLATION);
2190 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2191 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2192 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2196 if (pbEncoded[0] == ASN_INTEGER)
2198 DWORD bytesNeeded, dataLen;
2200 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2202 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2204 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2206 *pcbStructInfo = bytesNeeded;
2207 else if (*pcbStructInfo < bytesNeeded)
2209 *pcbStructInfo = bytesNeeded;
2210 SetLastError(ERROR_MORE_DATA);
2215 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2217 blob->cbData = dataLen;
2218 assert(blob->pbData);
2223 for (i = 0; i < blob->cbData; i++)
2225 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2234 SetLastError(CRYPT_E_ASN1_BADTAG);
2240 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2241 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2242 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2250 if ((ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2251 lpszStructType, pbEncoded, cbEncoded,
2252 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2255 *pcbStructInfo = bytesNeeded;
2256 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2257 pvStructInfo, pcbStructInfo, bytesNeeded)))
2259 CRYPT_INTEGER_BLOB *blob;
2261 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2262 pvStructInfo = *(BYTE **)pvStructInfo;
2263 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2264 blob->pbData = (BYTE *)pvStructInfo +
2265 sizeof(CRYPT_INTEGER_BLOB);
2266 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2267 lpszStructType, pbEncoded, cbEncoded,
2268 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2275 SetLastError(STATUS_ACCESS_VIOLATION);
2282 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
2283 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2284 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2285 void *pvStructInfo, DWORD *pcbStructInfo)
2289 if (pbEncoded[0] == ASN_INTEGER)
2291 DWORD bytesNeeded, dataLen;
2293 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2295 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2297 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2299 *pcbStructInfo = bytesNeeded;
2300 else if (*pcbStructInfo < bytesNeeded)
2302 *pcbStructInfo = bytesNeeded;
2303 SetLastError(ERROR_MORE_DATA);
2308 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2310 blob->cbData = dataLen;
2311 assert(blob->pbData);
2312 /* remove leading zero byte if it exists */
2313 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2322 for (i = 0; i < blob->cbData; i++)
2324 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2333 SetLastError(CRYPT_E_ASN1_BADTAG);
2339 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2340 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2341 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2349 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2350 lpszStructType, pbEncoded, cbEncoded,
2351 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2354 *pcbStructInfo = bytesNeeded;
2355 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2356 pvStructInfo, pcbStructInfo, bytesNeeded)))
2358 CRYPT_INTEGER_BLOB *blob;
2360 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2361 pvStructInfo = *(BYTE **)pvStructInfo;
2362 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2363 blob->pbData = (BYTE *)pvStructInfo +
2364 sizeof(CRYPT_INTEGER_BLOB);
2365 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2366 lpszStructType, pbEncoded, cbEncoded,
2367 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2374 SetLastError(STATUS_ACCESS_VIOLATION);
2381 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
2382 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2383 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2389 *pcbStructInfo = sizeof(int);
2394 if (pbEncoded[0] == ASN_ENUMERATED)
2396 unsigned int val = 0, i;
2400 SetLastError(CRYPT_E_ASN1_EOD);
2403 else if (pbEncoded[1] == 0)
2405 SetLastError(CRYPT_E_ASN1_CORRUPT);
2410 /* A little strange looking, but we have to accept a sign byte:
2411 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
2412 * assuming a small length is okay here, it has to be in short
2415 if (pbEncoded[1] > sizeof(unsigned int) + 1)
2417 SetLastError(CRYPT_E_ASN1_LARGE);
2420 for (i = 0; i < pbEncoded[1]; i++)
2423 val |= pbEncoded[2 + i];
2425 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2426 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
2428 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2429 pvStructInfo = *(BYTE **)pvStructInfo;
2430 memcpy(pvStructInfo, &val, sizeof(unsigned int));
2436 SetLastError(CRYPT_E_ASN1_BADTAG);
2442 SetLastError(STATUS_ACCESS_VIOLATION);
2449 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
2452 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
2457 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
2459 if (!isdigit(*(pbEncoded))) \
2461 SetLastError(CRYPT_E_ASN1_CORRUPT); \
2467 (word) += *(pbEncoded)++ - '0'; \
2472 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
2473 SYSTEMTIME *sysTime)
2480 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
2482 WORD hours, minutes = 0;
2483 BYTE sign = *pbEncoded++;
2486 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
2487 if (ret && hours >= 24)
2489 SetLastError(CRYPT_E_ASN1_CORRUPT);
2494 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
2495 if (ret && minutes >= 60)
2497 SetLastError(CRYPT_E_ASN1_CORRUPT);
2505 sysTime->wHour += hours;
2506 sysTime->wMinute += minutes;
2510 if (hours > sysTime->wHour)
2513 sysTime->wHour = 24 - (hours - sysTime->wHour);
2516 sysTime->wHour -= hours;
2517 if (minutes > sysTime->wMinute)
2520 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
2523 sysTime->wMinute -= minutes;
2530 SetLastError(STATUS_ACCESS_VIOLATION);
2537 #define MIN_ENCODED_TIME_LENGTH 10
2539 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
2540 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2541 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2547 *pcbStructInfo = sizeof(FILETIME);
2553 if (pbEncoded[0] == ASN_UTCTIME)
2557 SetLastError(CRYPT_E_ASN1_EOD);
2560 else if (pbEncoded[1] > 0x7f)
2562 /* long-form date strings really can't be valid */
2563 SetLastError(CRYPT_E_ASN1_CORRUPT);
2568 SYSTEMTIME sysTime = { 0 };
2569 BYTE len = pbEncoded[1];
2571 if (len < MIN_ENCODED_TIME_LENGTH)
2573 SetLastError(CRYPT_E_ASN1_CORRUPT);
2579 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
2580 if (sysTime.wYear >= 50)
2581 sysTime.wYear += 1900;
2583 sysTime.wYear += 2000;
2584 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2585 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2586 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2587 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
2590 if (len >= 2 && isdigit(*pbEncoded) &&
2591 isdigit(*(pbEncoded + 1)))
2592 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2594 else if (isdigit(*pbEncoded))
2595 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
2598 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2601 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2602 pDecodePara, pvStructInfo, pcbStructInfo,
2605 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2606 pvStructInfo = *(BYTE **)pvStructInfo;
2607 ret = SystemTimeToFileTime(&sysTime,
2608 (FILETIME *)pvStructInfo);
2615 SetLastError(CRYPT_E_ASN1_BADTAG);
2621 SetLastError(STATUS_ACCESS_VIOLATION);
2628 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
2629 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2630 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2636 *pcbStructInfo = sizeof(FILETIME);
2642 if (pbEncoded[0] == ASN_GENERALTIME)
2646 SetLastError(CRYPT_E_ASN1_EOD);
2649 else if (pbEncoded[1] > 0x7f)
2651 /* long-form date strings really can't be valid */
2652 SetLastError(CRYPT_E_ASN1_CORRUPT);
2657 BYTE len = pbEncoded[1];
2659 if (len < MIN_ENCODED_TIME_LENGTH)
2661 SetLastError(CRYPT_E_ASN1_CORRUPT);
2666 SYSTEMTIME sysTime = { 0 };
2669 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
2670 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2671 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2672 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2675 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2678 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2680 if (ret && len > 0 && (*pbEncoded == '.' ||
2687 /* workaround macro weirdness */
2688 digits = min(len, 3);
2689 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
2690 sysTime.wMilliseconds);
2693 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2696 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2697 pDecodePara, pvStructInfo, pcbStructInfo,
2700 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2701 pvStructInfo = *(BYTE **)pvStructInfo;
2702 ret = SystemTimeToFileTime(&sysTime,
2703 (FILETIME *)pvStructInfo);
2710 SetLastError(CRYPT_E_ASN1_BADTAG);
2716 SetLastError(STATUS_ACCESS_VIOLATION);
2723 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
2724 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2725 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2731 if (pbEncoded[0] == ASN_UTCTIME)
2732 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
2733 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2735 else if (pbEncoded[0] == ASN_GENERALTIME)
2736 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
2737 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
2738 pvStructInfo, pcbStructInfo);
2741 SetLastError(CRYPT_E_ASN1_BADTAG);
2747 SetLastError(STATUS_ACCESS_VIOLATION);
2754 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
2755 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2756 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2762 if (pbEncoded[0] == ASN_SEQUENCEOF)
2764 DWORD bytesNeeded, dataLen, remainingLen, cValue;
2766 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2771 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2772 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
2774 ptr = pbEncoded + 1 + lenBytes;
2775 remainingLen = dataLen;
2776 while (ret && remainingLen)
2780 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
2783 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
2785 remainingLen -= 1 + nextLenBytes + nextLen;
2786 ptr += 1 + nextLenBytes + nextLen;
2787 bytesNeeded += sizeof(CRYPT_DER_BLOB);
2788 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2789 bytesNeeded += 1 + nextLenBytes + nextLen;
2795 CRYPT_SEQUENCE_OF_ANY *seq;
2799 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2800 pvStructInfo, pcbStructInfo, bytesNeeded)))
2802 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2803 pvStructInfo = *(BYTE **)pvStructInfo;
2804 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2805 seq->cValue = cValue;
2806 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
2808 nextPtr = (BYTE *)seq->rgValue +
2809 cValue * sizeof(CRYPT_DER_BLOB);
2810 ptr = pbEncoded + 1 + lenBytes;
2811 remainingLen = dataLen;
2813 while (ret && remainingLen)
2817 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
2820 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
2822 seq->rgValue[i].cbData = 1 + nextLenBytes +
2824 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2825 seq->rgValue[i].pbData = (BYTE *)ptr;
2828 seq->rgValue[i].pbData = nextPtr;
2829 memcpy(nextPtr, ptr, 1 + nextLenBytes +
2831 nextPtr += 1 + nextLenBytes + nextLen;
2833 remainingLen -= 1 + nextLenBytes + nextLen;
2834 ptr += 1 + nextLenBytes + nextLen;
2844 SetLastError(CRYPT_E_ASN1_BADTAG);
2850 SetLastError(STATUS_ACCESS_VIOLATION);
2857 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
2858 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2859 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2861 struct AsnDecodeSequenceItem items[] = {
2862 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
2863 DistPointName), CRYPT_AsnDecodeAltNameInternal,
2864 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
2865 DistPointName.u.FullName.rgAltEntry), 0 },
2866 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
2867 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
2868 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
2869 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
2870 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
2871 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
2875 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2876 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2877 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2881 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
2882 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2883 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2887 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2888 pDecodePara, pvStructInfo, *pcbStructInfo);
2892 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2893 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
2894 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
2896 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2897 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2901 SetLastError(STATUS_ACCESS_VIOLATION);
2908 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
2909 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2910 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2914 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2915 pDecodePara, pvStructInfo, *pcbStructInfo);
2919 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2920 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2922 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2923 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2927 SetLastError(STATUS_ACCESS_VIOLATION);
2934 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2935 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2936 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2938 static HCRYPTOIDFUNCSET set = NULL;
2940 CryptDecodeObjectExFunc decodeFunc = NULL;
2941 HCRYPTOIDFUNCADDR hFunc = NULL;
2943 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
2944 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
2945 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
2947 if (!pvStructInfo && !pcbStructInfo)
2949 SetLastError(ERROR_INVALID_PARAMETER);
2952 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
2953 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
2955 SetLastError(ERROR_FILE_NOT_FOUND);
2960 SetLastError(CRYPT_E_ASN1_EOD);
2963 if (cbEncoded > MAX_ENCODED_LEN)
2965 SetLastError(CRYPT_E_ASN1_LARGE);
2969 SetLastError(NOERROR);
2970 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
2971 *(BYTE **)pvStructInfo = NULL;
2972 if (!HIWORD(lpszStructType))
2974 switch (LOWORD(lpszStructType))
2976 case (WORD)X509_CERT:
2977 decodeFunc = CRYPT_AsnDecodeCert;
2979 case (WORD)X509_CERT_TO_BE_SIGNED:
2980 decodeFunc = CRYPT_AsnDecodeCertInfo;
2982 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
2983 decodeFunc = CRYPT_AsnDecodeCRLInfo;
2985 case (WORD)X509_EXTENSIONS:
2986 decodeFunc = CRYPT_AsnDecodeExtensions;
2988 case (WORD)X509_NAME_VALUE:
2989 decodeFunc = CRYPT_AsnDecodeNameValue;
2991 case (WORD)X509_NAME:
2992 decodeFunc = CRYPT_AsnDecodeName;
2994 case (WORD)X509_PUBLIC_KEY_INFO:
2995 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
2997 case (WORD)X509_ALTERNATE_NAME:
2998 decodeFunc = CRYPT_AsnDecodeAltName;
3000 case (WORD)X509_BASIC_CONSTRAINTS:
3001 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3003 case (WORD)X509_BASIC_CONSTRAINTS2:
3004 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3006 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3007 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3009 case (WORD)X509_OCTET_STRING:
3010 decodeFunc = CRYPT_AsnDecodeOctets;
3012 case (WORD)X509_BITS:
3013 case (WORD)X509_KEY_USAGE:
3014 decodeFunc = CRYPT_AsnDecodeBits;
3016 case (WORD)X509_INTEGER:
3017 decodeFunc = CRYPT_AsnDecodeInt;
3019 case (WORD)X509_MULTI_BYTE_INTEGER:
3020 decodeFunc = CRYPT_AsnDecodeInteger;
3022 case (WORD)X509_MULTI_BYTE_UINT:
3023 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3025 case (WORD)X509_ENUMERATED:
3026 decodeFunc = CRYPT_AsnDecodeEnumerated;
3028 case (WORD)X509_CHOICE_OF_TIME:
3029 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3031 case (WORD)X509_SEQUENCE_OF_ANY:
3032 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3034 case (WORD)PKCS_UTC_TIME:
3035 decodeFunc = CRYPT_AsnDecodeUtcTime;
3037 case (WORD)X509_CRL_DIST_POINTS:
3038 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3040 case (WORD)X509_ENHANCED_KEY_USAGE:
3041 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3044 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3047 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3048 decodeFunc = CRYPT_AsnDecodeExtensions;
3049 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3050 decodeFunc = CRYPT_AsnDecodeUtcTime;
3051 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3052 decodeFunc = CRYPT_AsnDecodeEnumerated;
3053 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3054 decodeFunc = CRYPT_AsnDecodeBits;
3055 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3056 decodeFunc = CRYPT_AsnDecodeOctets;
3057 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3058 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3059 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3060 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3061 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3062 decodeFunc = CRYPT_AsnDecodeAltName;
3063 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3064 decodeFunc = CRYPT_AsnDecodeAltName;
3065 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3066 decodeFunc = CRYPT_AsnDecodeAltName;
3067 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3068 decodeFunc = CRYPT_AsnDecodeAltName;
3069 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3070 decodeFunc = CRYPT_AsnDecodeAltName;
3071 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3072 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3073 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3074 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3076 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3077 debugstr_a(lpszStructType));
3081 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
3082 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3083 (void **)&decodeFunc, &hFunc);
3086 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3087 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3089 SetLastError(ERROR_FILE_NOT_FOUND);
3091 CryptFreeOIDFunctionAddress(hFunc, 0);