2 * Copyright 2005-2007 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 isn't
21 * implemented, 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
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
38 #define NONAMELESSUNION
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "crypt32_private.h"
49 /* This is a bit arbitrary, but to set some limit: */
50 #define MAX_ENCODED_LEN 0x02000000
52 #define ASN_FLAGS_MASK 0xe0
53 #define ASN_TYPE_MASK 0x1f
55 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
56 WINE_DECLARE_DEBUG_CHANNEL(crypt
);
64 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
65 DWORD
, DWORD
, void *, DWORD
*);
66 typedef BOOL (WINAPI
*CryptDecodeObjectExFunc
)(DWORD
, LPCSTR
, const BYTE
*,
67 DWORD
, DWORD
, PCRYPT_DECODE_PARA
, void *, DWORD
*);
69 /* Internal decoders don't do memory allocation or exception handling, and
70 * they report how many bytes they decoded.
72 typedef BOOL (*InternalDecodeFunc
)(const BYTE
*pbEncoded
, DWORD cbEncoded
,
73 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
);
75 static BOOL
CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE
*pbEncoded
,
76 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
78 static BOOL
CRYPT_AsnDecodePubKeyInfoInternal(const BYTE
*pbEncoded
,
79 DWORD cbEncoded
, DWORD dwFlags
, 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.
84 static BOOL
CRYPT_AsnDecodeExtensionsInternal(const BYTE
*pbEncoded
,
85 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
87 /* Assumes algo->Parameters.pbData is set ahead of time. */
88 static BOOL
CRYPT_AsnDecodeAlgorithmId(const BYTE
*pbEncoded
, DWORD cbEncoded
,
89 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
);
90 static BOOL
CRYPT_AsnDecodeBool(const BYTE
*pbEncoded
, DWORD cbEncoded
,
91 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
);
92 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
93 static BOOL
CRYPT_AsnDecodeOctetsInternal(const BYTE
*pbEncoded
,
94 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
96 static BOOL
CRYPT_AsnDecodeBitsInternal(const BYTE
*pbEncoded
, DWORD cbEncoded
,
97 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
);
98 static BOOL
CRYPT_AsnDecodeIntInternal(const BYTE
*pbEncoded
, DWORD cbEncoded
,
99 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
);
100 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
101 * member has been initialized, doesn't do exception handling, and doesn't do
102 * memory allocation. Also doesn't check tag, assumes the caller has checked
105 static BOOL
CRYPT_AsnDecodeIntegerInternal(const BYTE
*pbEncoded
,
106 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
108 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
109 static BOOL
CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE
*pbEncoded
,
110 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
113 /* Gets the number of length bytes from the given (leading) length byte */
114 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
116 /* Helper function to get the encoded length of the data starting at pbEncoded,
117 * where pbEncoded[0] is the tag. If the data are too short to contain a
118 * length or if the length is too large for cbEncoded, sets an appropriate
119 * error code and returns FALSE. If the encoded length is unknown due to
120 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
122 static BOOL
CRYPT_GetLengthIndefinite(const BYTE
*pbEncoded
, DWORD cbEncoded
,
129 SetLastError(CRYPT_E_ASN1_CORRUPT
);
132 else if (pbEncoded
[1] <= 0x7f)
134 if (pbEncoded
[1] + 1 > cbEncoded
)
136 SetLastError(CRYPT_E_ASN1_EOD
);
145 else if (pbEncoded
[1] == 0x80)
147 *len
= CMSG_INDEFINITE_LENGTH
;
152 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
154 if (lenLen
> sizeof(DWORD
) + 1)
156 SetLastError(CRYPT_E_ASN1_LARGE
);
159 else if (lenLen
+ 2 > cbEncoded
)
161 SetLastError(CRYPT_E_ASN1_CORRUPT
);
174 if (out
+ lenLen
+ 1 > cbEncoded
)
176 SetLastError(CRYPT_E_ASN1_EOD
);
189 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
190 static BOOL
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD
*len
)
194 if ((ret
= CRYPT_GetLengthIndefinite(pbEncoded
, cbEncoded
, len
)) &&
195 *len
== CMSG_INDEFINITE_LENGTH
)
197 SetLastError(CRYPT_E_ASN1_CORRUPT
);
203 /* Helper function to check *pcbStructInfo, set it to the required size, and
204 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
205 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
206 * pointer to the newly allocated memory.
208 static BOOL
CRYPT_DecodeEnsureSpace(DWORD dwFlags
,
209 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
214 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
216 if (pDecodePara
&& pDecodePara
->pfnAlloc
)
217 *(BYTE
**)pvStructInfo
= pDecodePara
->pfnAlloc(bytesNeeded
);
219 *(BYTE
**)pvStructInfo
= LocalAlloc(0, bytesNeeded
);
220 if (!*(BYTE
**)pvStructInfo
)
223 *pcbStructInfo
= bytesNeeded
;
225 else if (*pcbStructInfo
< bytesNeeded
)
227 *pcbStructInfo
= bytesNeeded
;
228 SetLastError(ERROR_MORE_DATA
);
234 /* Helper function to check *pcbStructInfo and set it to the required size.
235 * Assumes pvStructInfo is not NULL.
237 static BOOL
CRYPT_DecodeCheckSpace(DWORD
*pcbStructInfo
, DWORD bytesNeeded
)
241 if (*pcbStructInfo
< bytesNeeded
)
243 *pcbStructInfo
= bytesNeeded
;
244 SetLastError(ERROR_MORE_DATA
);
249 *pcbStructInfo
= bytesNeeded
;
256 * The expected tag of the item. If tag is 0, decodeFunc is called
257 * regardless of the tag value seen.
259 * A sequence is decoded into a struct. The offset member is the
260 * offset of this item within that struct.
262 * The decoder function to use. If this is NULL, then the member isn't
263 * decoded, but minSize space is reserved for it.
265 * The minimum amount of space occupied after decoding. You must set this.
267 * If true, and the tag doesn't match the expected tag for this item,
268 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
269 * filled with 0 for this member.
270 * hasPointer, pointerOffset:
271 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
272 * the offset within the struct of the data pointer (or to the
273 * first data pointer, if more than one exist).
275 * Used by CRYPT_AsnDecodeSequence, not for your use.
277 struct AsnDecodeSequenceItem
281 InternalDecodeFunc decodeFunc
;
289 /* Decodes the items in a sequence, where the items are described in items,
290 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
291 * pvStructInfo. nextData is a pointer to the memory location at which the
292 * first decoded item with a dynamic pointer should point.
293 * Upon decoding, *cbDecoded is the total number of bytes decoded.
294 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
296 static BOOL
CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items
[],
297 DWORD cItem
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
298 void *pvStructInfo
, BYTE
*nextData
, DWORD
*cbDecoded
)
301 DWORD i
, decoded
= 0;
302 const BYTE
*ptr
= pbEncoded
;
304 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items
, cItem
, pbEncoded
,
305 cbEncoded
, dwFlags
, pvStructInfo
, nextData
, cbDecoded
);
307 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
309 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
313 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
316 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
318 if (ptr
[0] == items
[i
].tag
|| !items
[i
].tag
)
320 if (nextData
&& pvStructInfo
&& items
[i
].hasPointer
)
322 TRACE("Setting next pointer to %p\n",
324 *(BYTE
**)((BYTE
*)pvStructInfo
+
325 items
[i
].pointerOffset
) = nextData
;
327 if (items
[i
].decodeFunc
)
330 TRACE("decoding item %d\n", i
);
332 TRACE("sizing item %d\n", i
);
333 ret
= items
[i
].decodeFunc(ptr
,
334 1 + nextItemLenBytes
+ nextItemLen
,
335 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
,
336 pvStructInfo
? (BYTE
*)pvStructInfo
+ items
[i
].offset
337 : NULL
, &items
[i
].size
, NULL
);
340 /* Account for alignment padding */
341 if (items
[i
].size
% sizeof(DWORD_PTR
))
342 items
[i
].size
+= sizeof(DWORD_PTR
) -
343 items
[i
].size
% sizeof(DWORD_PTR
);
344 TRACE("item %d size: %d\n", i
, items
[i
].size
);
345 if (nextData
&& items
[i
].hasPointer
&&
346 items
[i
].size
> items
[i
].minSize
)
347 nextData
+= items
[i
].size
- items
[i
].minSize
;
348 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
349 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
350 TRACE("item %d: decoded %d bytes\n", i
,
351 1 + nextItemLenBytes
+ nextItemLen
);
353 else if (items
[i
].optional
&&
354 GetLastError() == CRYPT_E_ASN1_BADTAG
)
356 TRACE("skipping optional item %d\n", i
);
357 items
[i
].size
= items
[i
].minSize
;
358 SetLastError(NOERROR
);
362 TRACE("item %d failed: %08x\n", i
,
367 TRACE("item %d: decoded %d bytes\n", i
,
368 1 + nextItemLenBytes
+ nextItemLen
);
369 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
370 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
371 items
[i
].size
= items
[i
].minSize
;
374 else if (items
[i
].optional
)
376 TRACE("skipping optional item %d\n", i
);
377 items
[i
].size
= items
[i
].minSize
;
381 TRACE("item %d: tag %02x doesn't match expected %02x\n",
382 i
, ptr
[0], items
[i
].tag
);
383 SetLastError(CRYPT_E_ASN1_BADTAG
);
388 else if (items
[i
].optional
)
390 TRACE("missing optional item %d, skipping\n", i
);
391 items
[i
].size
= items
[i
].minSize
;
395 TRACE("not enough bytes for item %d, failing\n", i
);
396 SetLastError(CRYPT_E_ASN1_CORRUPT
);
401 *cbDecoded
= decoded
;
402 TRACE("returning %d\n", ret
);
406 /* This decodes an arbitrary sequence into a contiguous block of memory
407 * (basically, a struct.) Each element being decoded is described by a struct
408 * AsnDecodeSequenceItem, see above.
409 * startingPointer is an optional pointer to the first place where dynamic
410 * data will be stored. If you know the starting offset, you may pass it
411 * here. Otherwise, pass NULL, and one will be inferred from the items.
413 static BOOL
CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items
[],
414 DWORD cItem
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
415 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
416 DWORD
*pcbDecoded
, void *startingPointer
)
420 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items
, cItem
, pbEncoded
,
421 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
424 if (pbEncoded
[0] == ASN_SEQUENCE
)
428 if ((ret
= CRYPT_GetLengthIndefinite(pbEncoded
, cbEncoded
, &dataLen
)))
430 DWORD lenBytes
= GET_LEN_BYTES(pbEncoded
[1]), cbDecoded
;
431 const BYTE
*ptr
= pbEncoded
+ 1 + lenBytes
;
433 cbEncoded
-= 1 + lenBytes
;
434 if (dataLen
== CMSG_INDEFINITE_LENGTH
)
436 else if (cbEncoded
< dataLen
)
438 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen
,
440 SetLastError(CRYPT_E_ASN1_CORRUPT
);
447 ret
= CRYPT_AsnDecodeSequenceItems(items
, cItem
,
448 ptr
, cbEncoded
, dwFlags
, NULL
, NULL
, &cbDecoded
);
449 if (ret
&& dataLen
== CMSG_INDEFINITE_LENGTH
)
451 if (cbDecoded
> cbEncoded
- 2)
453 /* Not enough space for 0 TLV */
454 SetLastError(CRYPT_E_ASN1_CORRUPT
);
457 else if (*(ptr
+ cbDecoded
) != 0 ||
458 *(ptr
+ cbDecoded
+ 1) != 0)
460 TRACE("expected 0 TLV\n");
461 SetLastError(CRYPT_E_ASN1_CORRUPT
);
468 if (ret
&& cbDecoded
!= cbEncoded
)
470 TRACE("expected %d decoded, got %d, failing\n", cbEncoded
,
472 SetLastError(CRYPT_E_ASN1_CORRUPT
);
477 DWORD i
, bytesNeeded
= 0, structSize
= 0;
479 for (i
= 0; i
< cItem
; i
++)
481 bytesNeeded
+= items
[i
].size
;
482 structSize
+= items
[i
].minSize
;
484 if (ret
&& pcbDecoded
)
485 *pcbDecoded
= 1 + lenBytes
+ cbDecoded
;
487 *pcbStructInfo
= bytesNeeded
;
488 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
489 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
493 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
494 pvStructInfo
= *(BYTE
**)pvStructInfo
;
496 nextData
= (BYTE
*)startingPointer
;
498 nextData
= (BYTE
*)pvStructInfo
+ structSize
;
499 memset(pvStructInfo
, 0, structSize
);
500 ret
= CRYPT_AsnDecodeSequenceItems(items
, cItem
,
501 ptr
, cbEncoded
, dwFlags
, pvStructInfo
, nextData
,
509 SetLastError(CRYPT_E_ASN1_BADTAG
);
512 TRACE("returning %d (%08x)\n", ret
, GetLastError());
517 * The expected tag of the entire encoded array (usually a variant
518 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
519 * regardless of the tag seen.
521 * used to decode each item in the array
523 * is the minimum size of each decoded item
525 * indicates whether each item has a dynamic pointer
527 * indicates the offset within itemSize at which the pointer exists
529 struct AsnArrayDescriptor
532 InternalDecodeFunc decodeFunc
;
538 struct AsnArrayItemSize
544 /* Decodes an array of like types into a struct GenericArray.
545 * The layout and decoding of the array are described by a struct
546 * AsnArrayDescriptor.
548 static BOOL
CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor
*arrayDesc
,
549 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
550 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
551 DWORD
*pcbDecoded
, void *startingPointer
)
555 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc
, pbEncoded
,
556 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
559 if (!arrayDesc
->tag
|| pbEncoded
[0] == arrayDesc
->tag
)
563 if ((ret
= CRYPT_GetLengthIndefinite(pbEncoded
, cbEncoded
, &dataLen
)))
565 DWORD bytesNeeded
, cItems
= 0, decoded
;
566 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
567 /* There can be arbitrarily many items, but there is often only one.
569 struct AsnArrayItemSize itemSize
= { 0 }, *itemSizes
= &itemSize
;
571 decoded
= 1 + lenBytes
;
572 bytesNeeded
= sizeof(struct GenericArray
);
576 BOOL doneDecoding
= FALSE
;
578 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&& !doneDecoding
; )
582 itemLenBytes
= GET_LEN_BYTES(ptr
[1]);
583 if (dataLen
== CMSG_INDEFINITE_LENGTH
)
588 if (itemLenBytes
!= 1 || ptr
[1] != 0)
590 SetLastError(CRYPT_E_ASN1_CORRUPT
);
597 else if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
)
601 DWORD itemEncoded
, itemDataLen
, itemDecoded
, size
= 0;
603 /* Each item decoded may not tolerate extraneous bytes,
604 * so get the length of the next element if known.
606 if ((ret
= CRYPT_GetLengthIndefinite(ptr
,
607 cbEncoded
- (ptr
- pbEncoded
), &itemDataLen
)))
609 if (itemDataLen
== CMSG_INDEFINITE_LENGTH
)
610 itemEncoded
= cbEncoded
- (ptr
- pbEncoded
);
612 itemEncoded
= 1 + itemLenBytes
+ itemDataLen
;
615 ret
= arrayDesc
->decodeFunc(ptr
, itemEncoded
,
616 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &size
,
621 if (itemSizes
!= &itemSize
)
622 itemSizes
= CryptMemRealloc(itemSizes
,
623 cItems
* sizeof(struct AsnArrayItemSize
));
628 cItems
* sizeof(struct AsnArrayItemSize
));
630 memcpy(itemSizes
, &itemSize
,
635 decoded
+= itemDecoded
;
636 itemSizes
[cItems
- 1].encodedLen
= itemEncoded
;
637 itemSizes
[cItems
- 1].size
= size
;
650 *pcbDecoded
= decoded
;
652 *pcbStructInfo
= bytesNeeded
;
653 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
654 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
659 struct GenericArray
*array
;
661 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
662 pvStructInfo
= *(BYTE
**)pvStructInfo
;
663 array
= (struct GenericArray
*)pvStructInfo
;
664 array
->cItems
= cItems
;
666 array
->rgItems
= startingPointer
;
668 array
->rgItems
= (BYTE
*)array
+
669 sizeof(struct GenericArray
);
670 nextData
= (BYTE
*)array
->rgItems
+
671 array
->cItems
* arrayDesc
->itemSize
;
672 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
673 i
< cItems
&& ptr
- pbEncoded
- 1 - lenBytes
<
676 if (arrayDesc
->hasPointer
)
677 *(BYTE
**)(array
->rgItems
+ i
* arrayDesc
->itemSize
678 + arrayDesc
->pointerOffset
) = nextData
;
679 ret
= arrayDesc
->decodeFunc(ptr
,
680 itemSizes
[i
].encodedLen
,
681 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
,
682 array
->rgItems
+ i
* arrayDesc
->itemSize
,
683 &itemSizes
[i
].size
, NULL
);
688 nextData
+= itemSizes
[i
].size
- arrayDesc
->itemSize
;
689 ret
= CRYPT_GetLen(ptr
,
690 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
692 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
697 if (itemSizes
!= &itemSize
)
698 CryptMemFree(itemSizes
);
703 SetLastError(CRYPT_E_ASN1_BADTAG
);
709 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
710 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
711 * to CRYPT_E_ASN1_CORRUPT.
712 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
715 static BOOL
CRYPT_AsnDecodeDerBlob(const BYTE
*pbEncoded
, DWORD cbEncoded
,
716 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
721 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
723 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
724 DWORD bytesNeeded
= sizeof(CRYPT_DER_BLOB
);
726 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
727 bytesNeeded
+= 1 + lenBytes
+ dataLen
;
730 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
732 *pcbStructInfo
= bytesNeeded
;
733 else if ((ret
= CRYPT_DecodeCheckSpace(pcbStructInfo
, bytesNeeded
)))
735 CRYPT_DER_BLOB
*blob
;
737 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
738 pvStructInfo
= *(BYTE
**)pvStructInfo
;
739 blob
= (CRYPT_DER_BLOB
*)pvStructInfo
;
740 blob
->cbData
= 1 + lenBytes
+ dataLen
;
743 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
744 blob
->pbData
= (BYTE
*)pbEncoded
;
747 assert(blob
->pbData
);
748 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
753 SetLastError(CRYPT_E_ASN1_CORRUPT
);
761 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
762 static BOOL
CRYPT_AsnDecodeBitsSwapBytes(const BYTE
*pbEncoded
,
763 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
768 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
769 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
771 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
774 ret
= CRYPT_AsnDecodeBitsInternal(pbEncoded
, cbEncoded
,
775 dwFlags
& ~CRYPT_DECODE_NOCOPY_FLAG
, pvStructInfo
, pcbStructInfo
,
777 if (ret
&& pvStructInfo
)
779 CRYPT_BIT_BLOB
*blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
786 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
788 temp
= blob
->pbData
[i
];
789 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
790 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
794 TRACE("returning %d (%08x)\n", ret
, GetLastError());
798 static BOOL WINAPI
CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType
,
799 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
800 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
804 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
805 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
809 struct AsnDecodeSequenceItem items
[] = {
810 { 0, offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
),
811 CRYPT_AsnDecodeDerBlob
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
812 offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
.pbData
), 0 },
813 { ASN_SEQUENCEOF
, offsetof(CERT_SIGNED_CONTENT_INFO
,
814 SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
815 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
,
816 offsetof(CERT_SIGNED_CONTENT_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
817 { ASN_BITSTRING
, offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
),
818 CRYPT_AsnDecodeBitsSwapBytes
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
819 offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
.pbData
), 0 },
822 if (dwFlags
& CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
823 items
[2].decodeFunc
= CRYPT_AsnDecodeBitsInternal
;
824 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
825 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
826 pcbStructInfo
, NULL
, NULL
);
830 SetLastError(STATUS_ACCESS_VIOLATION
);
835 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
839 static BOOL
CRYPT_AsnDecodeCertVersion(const BYTE
*pbEncoded
, DWORD cbEncoded
,
840 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
845 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
847 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
849 ret
= CRYPT_AsnDecodeIntInternal(pbEncoded
+ 1 + lenBytes
, dataLen
,
850 dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
852 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
857 static BOOL
CRYPT_AsnDecodeValidity(const BYTE
*pbEncoded
, DWORD cbEncoded
,
858 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
862 struct AsnDecodeSequenceItem items
[] = {
863 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotBefore
),
864 CRYPT_AsnDecodeChoiceOfTimeInternal
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
865 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotAfter
),
866 CRYPT_AsnDecodeChoiceOfTimeInternal
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
869 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
870 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
875 static BOOL
CRYPT_AsnDecodeCertExtensions(const BYTE
*pbEncoded
,
876 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
882 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
884 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
886 ret
= CRYPT_AsnDecodeExtensionsInternal(pbEncoded
+ 1 + lenBytes
,
887 dataLen
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
888 if (ret
&& pcbDecoded
)
889 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
894 static BOOL WINAPI
CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType
,
895 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
896 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
899 struct AsnDecodeSequenceItem items
[] = {
900 { ASN_CONTEXT
| ASN_CONSTRUCTOR
, offsetof(CERT_INFO
, dwVersion
),
901 CRYPT_AsnDecodeCertVersion
, sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
902 { ASN_INTEGER
, offsetof(CERT_INFO
, SerialNumber
),
903 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
,
904 TRUE
, offsetof(CERT_INFO
, SerialNumber
.pbData
), 0 },
905 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, SignatureAlgorithm
),
906 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
907 FALSE
, TRUE
, offsetof(CERT_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
908 { 0, offsetof(CERT_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
909 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
911 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, NotBefore
),
912 CRYPT_AsnDecodeValidity
, sizeof(CERT_PRIVATE_KEY_VALIDITY
), FALSE
,
914 { 0, offsetof(CERT_INFO
, Subject
), CRYPT_AsnDecodeDerBlob
,
915 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
917 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, SubjectPublicKeyInfo
),
918 CRYPT_AsnDecodePubKeyInfoInternal
, sizeof(CERT_PUBLIC_KEY_INFO
),
919 FALSE
, TRUE
, offsetof(CERT_INFO
,
920 SubjectPublicKeyInfo
.Algorithm
.Parameters
.pbData
), 0 },
921 { ASN_BITSTRING
, offsetof(CERT_INFO
, IssuerUniqueId
),
922 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
923 offsetof(CERT_INFO
, IssuerUniqueId
.pbData
), 0 },
924 { ASN_BITSTRING
, offsetof(CERT_INFO
, SubjectUniqueId
),
925 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
926 offsetof(CERT_INFO
, SubjectUniqueId
.pbData
), 0 },
927 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 3, offsetof(CERT_INFO
, cExtension
),
928 CRYPT_AsnDecodeCertExtensions
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
929 offsetof(CERT_INFO
, rgExtension
), 0 },
932 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
933 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
935 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
936 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
,
938 if (ret
&& pvStructInfo
)
942 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
943 info
= *(CERT_INFO
**)pvStructInfo
;
945 info
= (CERT_INFO
*)pvStructInfo
;
946 if (!info
->SerialNumber
.cbData
|| !info
->Issuer
.cbData
||
947 !info
->Subject
.cbData
)
949 SetLastError(CRYPT_E_ASN1_CORRUPT
);
950 /* Don't need to deallocate, because it should have failed on the
951 * first pass (and no memory was allocated.)
957 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
961 static BOOL WINAPI
CRYPT_AsnDecodeCert(DWORD dwCertEncodingType
,
962 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
963 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
967 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
968 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
974 /* Unless told not to, first try to decode it as a signed cert. */
975 if (!(dwFlags
& CRYPT_DECODE_TO_BE_SIGNED_FLAG
))
977 PCERT_SIGNED_CONTENT_INFO signedCert
= NULL
;
979 ret
= CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType
,
980 X509_CERT
, pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
981 (BYTE
*)&signedCert
, &size
);
985 ret
= CRYPT_AsnDecodeCertInfo(dwCertEncodingType
,
986 X509_CERT_TO_BE_SIGNED
, signedCert
->ToBeSigned
.pbData
,
987 signedCert
->ToBeSigned
.cbData
, dwFlags
, pDecodePara
,
988 pvStructInfo
, pcbStructInfo
);
989 LocalFree(signedCert
);
992 /* Failing that, try it as an unsigned cert */
996 ret
= CRYPT_AsnDecodeCertInfo(dwCertEncodingType
,
997 X509_CERT_TO_BE_SIGNED
, pbEncoded
, cbEncoded
, dwFlags
,
998 pDecodePara
, pvStructInfo
, pcbStructInfo
);
1003 SetLastError(STATUS_ACCESS_VIOLATION
);
1007 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
1011 static BOOL
CRYPT_AsnDecodeCRLEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1012 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1015 struct AsnDecodeSequenceItem items
[] = {
1016 { ASN_INTEGER
, offsetof(CRL_ENTRY
, SerialNumber
),
1017 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
,
1018 offsetof(CRL_ENTRY
, SerialNumber
.pbData
), 0 },
1019 { 0, offsetof(CRL_ENTRY
, RevocationDate
),
1020 CRYPT_AsnDecodeChoiceOfTimeInternal
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
1021 { ASN_SEQUENCEOF
, offsetof(CRL_ENTRY
, cExtension
),
1022 CRYPT_AsnDecodeExtensionsInternal
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
1023 offsetof(CRL_ENTRY
, rgExtension
), 0 },
1025 PCRL_ENTRY entry
= (PCRL_ENTRY
)pvStructInfo
;
1027 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
, entry
,
1030 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
1031 pbEncoded
, cbEncoded
, dwFlags
, NULL
, entry
, pcbStructInfo
, pcbDecoded
,
1032 entry
? entry
->SerialNumber
.pbData
: NULL
);
1036 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1037 * been set prior to calling.
1039 static BOOL
CRYPT_AsnDecodeCRLEntries(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1040 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1043 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1044 CRYPT_AsnDecodeCRLEntry
, sizeof(CRL_ENTRY
), TRUE
,
1045 offsetof(CRL_ENTRY
, SerialNumber
.pbData
) };
1046 struct GenericArray
*entries
= (struct GenericArray
*)pvStructInfo
;
1048 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
1049 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
1051 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1052 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
1053 entries
? entries
->rgItems
: NULL
);
1054 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
1058 static BOOL WINAPI
CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType
,
1059 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1060 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1062 struct AsnDecodeSequenceItem items
[] = {
1063 { ASN_INTEGER
, offsetof(CRL_INFO
, dwVersion
),
1064 CRYPT_AsnDecodeIntInternal
, sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
1065 { ASN_SEQUENCEOF
, offsetof(CRL_INFO
, SignatureAlgorithm
),
1066 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
1067 FALSE
, TRUE
, offsetof(CRL_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
1068 { 0, offsetof(CRL_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
1069 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CRL_INFO
,
1071 { 0, offsetof(CRL_INFO
, ThisUpdate
), CRYPT_AsnDecodeChoiceOfTimeInternal
,
1072 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
1073 { 0, offsetof(CRL_INFO
, NextUpdate
), CRYPT_AsnDecodeChoiceOfTimeInternal
,
1074 sizeof(FILETIME
), TRUE
, FALSE
, 0 },
1075 { ASN_SEQUENCEOF
, offsetof(CRL_INFO
, cCRLEntry
),
1076 CRYPT_AsnDecodeCRLEntries
, sizeof(struct GenericArray
), TRUE
, TRUE
,
1077 offsetof(CRL_INFO
, rgCRLEntry
), 0 },
1078 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_INFO
, cExtension
),
1079 CRYPT_AsnDecodeCertExtensions
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
1080 offsetof(CRL_INFO
, rgExtension
), 0 },
1084 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1085 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1087 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
1088 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
,
1091 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
1095 static BOOL WINAPI
CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType
,
1096 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1097 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1101 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1102 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1108 /* Unless told not to, first try to decode it as a signed crl. */
1109 if (!(dwFlags
& CRYPT_DECODE_TO_BE_SIGNED_FLAG
))
1111 PCERT_SIGNED_CONTENT_INFO signedCrl
= NULL
;
1113 ret
= CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType
,
1114 X509_CERT
, pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
1115 (BYTE
*)&signedCrl
, &size
);
1119 ret
= CRYPT_AsnDecodeCRLInfo(dwCertEncodingType
,
1120 X509_CERT_CRL_TO_BE_SIGNED
, signedCrl
->ToBeSigned
.pbData
,
1121 signedCrl
->ToBeSigned
.cbData
, dwFlags
, pDecodePara
,
1122 pvStructInfo
, pcbStructInfo
);
1123 LocalFree(signedCrl
);
1126 /* Failing that, try it as an unsigned crl */
1130 ret
= CRYPT_AsnDecodeCRLInfo(dwCertEncodingType
,
1131 X509_CERT_CRL_TO_BE_SIGNED
, pbEncoded
, cbEncoded
,
1132 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
1137 SetLastError(STATUS_ACCESS_VIOLATION
);
1141 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
1145 static BOOL
CRYPT_AsnDecodeOidIgnoreTag(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1146 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1151 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1152 pvStructInfo
, *pcbStructInfo
);
1154 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1156 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1157 DWORD bytesNeeded
= sizeof(LPSTR
);
1161 /* The largest possible string for the first two components
1162 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1167 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
1168 pbEncoded
[1 + lenBytes
] / 40,
1169 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
1171 bytesNeeded
+= strlen(firstTwo
) + 1;
1172 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1173 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1175 /* large enough for ".4000000" */
1179 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1186 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
1189 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1196 snprintf(str
, sizeof(str
), ".%d", val
);
1197 bytesNeeded
+= strlen(str
);
1202 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
1204 *pcbStructInfo
= bytesNeeded
;
1205 else if (*pcbStructInfo
< bytesNeeded
)
1207 *pcbStructInfo
= bytesNeeded
;
1208 SetLastError(ERROR_MORE_DATA
);
1216 LPSTR pszObjId
= *(LPSTR
*)pvStructInfo
;
1219 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
1220 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
1222 pszObjId
+= strlen(pszObjId
);
1223 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1224 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1228 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1237 sprintf(pszObjId
, ".%d", val
);
1238 pszObjId
+= strlen(pszObjId
);
1242 *(LPSTR
*)pvStructInfo
= NULL
;
1243 *pcbStructInfo
= bytesNeeded
;
1249 static BOOL
CRYPT_AsnDecodeOidInternal(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1250 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1254 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1255 pvStructInfo
, *pcbStructInfo
);
1257 if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
1258 ret
= CRYPT_AsnDecodeOidIgnoreTag(pbEncoded
, cbEncoded
, dwFlags
,
1259 pvStructInfo
, pcbStructInfo
, pcbDecoded
);
1262 SetLastError(CRYPT_E_ASN1_BADTAG
);
1268 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1271 static BOOL
CRYPT_AsnDecodeExtension(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1272 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1274 struct AsnDecodeSequenceItem items
[] = {
1275 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_EXTENSION
, pszObjId
),
1276 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1277 offsetof(CERT_EXTENSION
, pszObjId
), 0 },
1278 { ASN_BOOL
, offsetof(CERT_EXTENSION
, fCritical
), CRYPT_AsnDecodeBool
,
1279 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
1280 { ASN_OCTETSTRING
, offsetof(CERT_EXTENSION
, Value
),
1281 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_OBJID_BLOB
), FALSE
, TRUE
,
1282 offsetof(CERT_EXTENSION
, Value
.pbData
) },
1285 PCERT_EXTENSION ext
= (PCERT_EXTENSION
)pvStructInfo
;
1287 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
, ext
,
1291 TRACE("ext->pszObjId is %p\n", ext
->pszObjId
);
1292 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
1293 pbEncoded
, cbEncoded
, dwFlags
, NULL
, ext
, pcbStructInfo
,
1294 pcbDecoded
, ext
? ext
->pszObjId
: NULL
);
1296 TRACE("ext->pszObjId is %p (%s)\n", ext
->pszObjId
,
1297 debugstr_a(ext
->pszObjId
));
1298 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1302 static BOOL
CRYPT_AsnDecodeExtensionsInternal(const BYTE
*pbEncoded
,
1303 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1307 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1308 CRYPT_AsnDecodeExtension
, sizeof(CERT_EXTENSION
), TRUE
,
1309 offsetof(CERT_EXTENSION
, pszObjId
) };
1310 PCERT_EXTENSIONS exts
= (PCERT_EXTENSIONS
)pvStructInfo
;
1312 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
1313 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
1315 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1316 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
1317 exts
? exts
->rgExtension
: NULL
);
1321 static BOOL WINAPI
CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType
,
1322 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1323 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1329 ret
= CRYPT_AsnDecodeExtensionsInternal(pbEncoded
, cbEncoded
,
1330 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pcbStructInfo
, NULL
);
1331 if (ret
&& pvStructInfo
)
1333 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
1334 pcbStructInfo
, *pcbStructInfo
);
1337 CERT_EXTENSIONS
*exts
;
1339 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1340 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1341 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
1342 exts
->rgExtension
= (CERT_EXTENSION
*)((BYTE
*)exts
+
1343 sizeof(CERT_EXTENSIONS
));
1344 ret
= CRYPT_AsnDecodeExtensionsInternal(pbEncoded
, cbEncoded
,
1345 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
1346 pcbStructInfo
, NULL
);
1352 SetLastError(STATUS_ACCESS_VIOLATION
);
1359 /* Warning: this assumes the address of value->Value.pbData is already set, in
1360 * order to avoid overwriting memory. (In some cases, it may change it, if it
1361 * doesn't copy anything to memory.) Be sure to set it correctly!
1363 static BOOL
CRYPT_AsnDecodeNameValueInternal(const BYTE
*pbEncoded
,
1364 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1369 CERT_NAME_VALUE
*value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1371 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1373 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1374 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
), valueType
;
1376 switch (pbEncoded
[0])
1378 case ASN_OCTETSTRING
:
1379 valueType
= CERT_RDN_OCTET_STRING
;
1380 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1381 bytesNeeded
+= dataLen
;
1383 case ASN_NUMERICSTRING
:
1384 valueType
= CERT_RDN_NUMERIC_STRING
;
1385 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1386 bytesNeeded
+= dataLen
;
1388 case ASN_PRINTABLESTRING
:
1389 valueType
= CERT_RDN_PRINTABLE_STRING
;
1390 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1391 bytesNeeded
+= dataLen
;
1394 valueType
= CERT_RDN_IA5_STRING
;
1395 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1396 bytesNeeded
+= dataLen
;
1399 valueType
= CERT_RDN_T61_STRING
;
1400 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1401 bytesNeeded
+= dataLen
;
1403 case ASN_VIDEOTEXSTRING
:
1404 valueType
= CERT_RDN_VIDEOTEX_STRING
;
1405 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1406 bytesNeeded
+= dataLen
;
1408 case ASN_GRAPHICSTRING
:
1409 valueType
= CERT_RDN_GRAPHIC_STRING
;
1410 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1411 bytesNeeded
+= dataLen
;
1413 case ASN_VISIBLESTRING
:
1414 valueType
= CERT_RDN_VISIBLE_STRING
;
1415 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1416 bytesNeeded
+= dataLen
;
1418 case ASN_GENERALSTRING
:
1419 valueType
= CERT_RDN_GENERAL_STRING
;
1420 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1421 bytesNeeded
+= dataLen
;
1423 case ASN_UNIVERSALSTRING
:
1424 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1425 SetLastError(CRYPT_E_ASN1_BADTAG
);
1428 valueType
= CERT_RDN_BMP_STRING
;
1429 bytesNeeded
+= dataLen
;
1431 case ASN_UTF8STRING
:
1432 valueType
= CERT_RDN_UTF8_STRING
;
1433 bytesNeeded
+= MultiByteToWideChar(CP_UTF8
, 0,
1434 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
, NULL
, 0) * 2;
1437 SetLastError(CRYPT_E_ASN1_BADTAG
);
1442 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
1444 *pcbStructInfo
= bytesNeeded
;
1445 else if (*pcbStructInfo
< bytesNeeded
)
1447 *pcbStructInfo
= bytesNeeded
;
1448 SetLastError(ERROR_MORE_DATA
);
1453 *pcbStructInfo
= bytesNeeded
;
1454 value
->dwValueType
= valueType
;
1459 assert(value
->Value
.pbData
);
1460 switch (pbEncoded
[0])
1462 case ASN_OCTETSTRING
:
1463 case ASN_NUMERICSTRING
:
1464 case ASN_PRINTABLESTRING
:
1467 case ASN_VIDEOTEXSTRING
:
1468 case ASN_GRAPHICSTRING
:
1469 case ASN_VISIBLESTRING
:
1470 case ASN_GENERALSTRING
:
1471 value
->Value
.cbData
= dataLen
;
1474 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1475 memcpy(value
->Value
.pbData
,
1476 pbEncoded
+ 1 + lenBytes
, dataLen
);
1478 value
->Value
.pbData
= (LPBYTE
)pbEncoded
+ 1 +
1484 LPWSTR str
= (LPWSTR
)value
->Value
.pbData
;
1486 value
->Value
.cbData
= dataLen
;
1487 for (i
= 0; i
< dataLen
/ 2; i
++)
1488 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
1489 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
1492 case ASN_UTF8STRING
:
1494 LPWSTR str
= (LPWSTR
)value
->Value
.pbData
;
1496 value
->Value
.cbData
= MultiByteToWideChar(CP_UTF8
, 0,
1497 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
,
1498 str
, bytesNeeded
- sizeof(CERT_NAME_VALUE
)) * 2;
1505 value
->Value
.cbData
= 0;
1506 value
->Value
.pbData
= NULL
;
1513 static BOOL WINAPI
CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType
,
1514 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1515 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1521 ret
= CRYPT_AsnDecodeNameValueInternal(pbEncoded
, cbEncoded
,
1522 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pcbStructInfo
, NULL
);
1523 if (ret
&& pvStructInfo
)
1525 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
1526 pcbStructInfo
, *pcbStructInfo
);
1529 CERT_NAME_VALUE
*value
;
1531 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1532 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1533 value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1534 value
->Value
.pbData
= ((BYTE
*)value
+ sizeof(CERT_NAME_VALUE
));
1535 ret
= CRYPT_AsnDecodeNameValueInternal( pbEncoded
, cbEncoded
,
1536 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
1537 pcbStructInfo
, NULL
);
1543 SetLastError(STATUS_ACCESS_VIOLATION
);
1550 static BOOL
CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE
*pbEncoded
,
1551 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1556 CERT_NAME_VALUE
*value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1558 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1560 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1561 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
), valueType
;
1563 switch (pbEncoded
[0])
1565 case ASN_NUMERICSTRING
:
1566 valueType
= CERT_RDN_NUMERIC_STRING
;
1567 bytesNeeded
+= dataLen
* 2;
1569 case ASN_PRINTABLESTRING
:
1570 valueType
= CERT_RDN_PRINTABLE_STRING
;
1571 bytesNeeded
+= dataLen
* 2;
1574 valueType
= CERT_RDN_IA5_STRING
;
1575 bytesNeeded
+= dataLen
* 2;
1578 valueType
= CERT_RDN_T61_STRING
;
1579 bytesNeeded
+= dataLen
* 2;
1581 case ASN_VIDEOTEXSTRING
:
1582 valueType
= CERT_RDN_VIDEOTEX_STRING
;
1583 bytesNeeded
+= dataLen
* 2;
1585 case ASN_GRAPHICSTRING
:
1586 valueType
= CERT_RDN_GRAPHIC_STRING
;
1587 bytesNeeded
+= dataLen
* 2;
1589 case ASN_VISIBLESTRING
:
1590 valueType
= CERT_RDN_VISIBLE_STRING
;
1591 bytesNeeded
+= dataLen
* 2;
1593 case ASN_GENERALSTRING
:
1594 valueType
= CERT_RDN_GENERAL_STRING
;
1595 bytesNeeded
+= dataLen
* 2;
1597 case ASN_UNIVERSALSTRING
:
1598 valueType
= CERT_RDN_UNIVERSAL_STRING
;
1599 bytesNeeded
+= dataLen
/ 2;
1602 valueType
= CERT_RDN_BMP_STRING
;
1603 bytesNeeded
+= dataLen
;
1605 case ASN_UTF8STRING
:
1606 valueType
= CERT_RDN_UTF8_STRING
;
1607 bytesNeeded
+= MultiByteToWideChar(CP_UTF8
, 0,
1608 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
, NULL
, 0) * 2;
1611 SetLastError(CRYPT_E_ASN1_BADTAG
);
1616 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
1618 *pcbStructInfo
= bytesNeeded
;
1619 else if (*pcbStructInfo
< bytesNeeded
)
1621 *pcbStructInfo
= bytesNeeded
;
1622 SetLastError(ERROR_MORE_DATA
);
1627 *pcbStructInfo
= bytesNeeded
;
1628 value
->dwValueType
= valueType
;
1632 LPWSTR str
= (LPWSTR
)value
->Value
.pbData
;
1634 assert(value
->Value
.pbData
);
1635 switch (pbEncoded
[0])
1637 case ASN_NUMERICSTRING
:
1638 case ASN_PRINTABLESTRING
:
1641 case ASN_VIDEOTEXSTRING
:
1642 case ASN_GRAPHICSTRING
:
1643 case ASN_VISIBLESTRING
:
1644 case ASN_GENERALSTRING
:
1645 value
->Value
.cbData
= dataLen
* 2;
1646 for (i
= 0; i
< dataLen
; i
++)
1647 str
[i
] = pbEncoded
[1 + lenBytes
+ i
];
1649 case ASN_UNIVERSALSTRING
:
1650 value
->Value
.cbData
= dataLen
/ 2;
1651 for (i
= 0; i
< dataLen
/ 4; i
++)
1652 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
+ 2] << 8)
1653 | pbEncoded
[1 + lenBytes
+ 2 * i
+ 3];
1656 value
->Value
.cbData
= dataLen
;
1657 for (i
= 0; i
< dataLen
/ 2; i
++)
1658 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
1659 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
1661 case ASN_UTF8STRING
:
1662 value
->Value
.cbData
= MultiByteToWideChar(CP_UTF8
, 0,
1663 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
,
1664 str
, bytesNeeded
- sizeof(CERT_NAME_VALUE
)) * 2;
1670 value
->Value
.cbData
= 0;
1671 value
->Value
.pbData
= NULL
;
1678 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType
,
1679 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1680 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1686 ret
= CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded
, cbEncoded
,
1687 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pcbStructInfo
, NULL
);
1688 if (ret
&& pvStructInfo
)
1690 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
1691 pcbStructInfo
, *pcbStructInfo
);
1694 CERT_NAME_VALUE
*value
;
1696 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1697 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1698 value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1699 value
->Value
.pbData
= ((BYTE
*)value
+ sizeof(CERT_NAME_VALUE
));
1700 ret
= CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded
,
1701 cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
1702 pcbStructInfo
, NULL
);
1708 SetLastError(STATUS_ACCESS_VIOLATION
);
1715 static BOOL
CRYPT_AsnDecodeRdnAttr(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1716 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1719 struct AsnDecodeSequenceItem items
[] = {
1720 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_RDN_ATTR
, pszObjId
),
1721 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1722 offsetof(CERT_RDN_ATTR
, pszObjId
), 0 },
1723 { 0, offsetof(CERT_RDN_ATTR
, dwValueType
),
1724 CRYPT_AsnDecodeNameValueInternal
, sizeof(CERT_NAME_VALUE
),
1725 FALSE
, TRUE
, offsetof(CERT_RDN_ATTR
, Value
.pbData
), 0 },
1727 CERT_RDN_ATTR
*attr
= (CERT_RDN_ATTR
*)pvStructInfo
;
1729 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1730 pvStructInfo
, *pcbStructInfo
);
1733 TRACE("attr->pszObjId is %p\n", attr
->pszObjId
);
1734 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
1735 pbEncoded
, cbEncoded
, dwFlags
, NULL
, attr
, pcbStructInfo
, pcbDecoded
,
1736 attr
? attr
->pszObjId
: NULL
);
1739 TRACE("attr->pszObjId is %p (%s)\n", attr
->pszObjId
,
1740 debugstr_a(attr
->pszObjId
));
1741 TRACE("attr->dwValueType is %d\n", attr
->dwValueType
);
1743 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1747 static BOOL
CRYPT_AsnDecodeRdn(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1748 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1751 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
1752 CRYPT_AsnDecodeRdnAttr
, sizeof(CERT_RDN_ATTR
), TRUE
,
1753 offsetof(CERT_RDN_ATTR
, pszObjId
) };
1754 PCERT_RDN rdn
= (PCERT_RDN
)pvStructInfo
;
1756 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1757 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
1758 rdn
? rdn
->rgRDNAttr
: NULL
);
1762 static BOOL WINAPI
CRYPT_AsnDecodeName(DWORD dwCertEncodingType
,
1763 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1764 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1770 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1771 CRYPT_AsnDecodeRdn
, sizeof(CERT_RDN
), TRUE
,
1772 offsetof(CERT_RDN
, rgRDNAttr
) };
1774 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1775 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
, NULL
);
1779 SetLastError(STATUS_ACCESS_VIOLATION
);
1786 static BOOL
CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE
*pbEncoded
,
1787 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1791 struct AsnDecodeSequenceItem items
[] = {
1792 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_RDN_ATTR
, pszObjId
),
1793 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1794 offsetof(CERT_RDN_ATTR
, pszObjId
), 0 },
1795 { 0, offsetof(CERT_RDN_ATTR
, dwValueType
),
1796 CRYPT_AsnDecodeUnicodeNameValueInternal
, sizeof(CERT_NAME_VALUE
),
1797 FALSE
, TRUE
, offsetof(CERT_RDN_ATTR
, Value
.pbData
), 0 },
1799 CERT_RDN_ATTR
*attr
= (CERT_RDN_ATTR
*)pvStructInfo
;
1801 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1802 pvStructInfo
, *pcbStructInfo
);
1805 TRACE("attr->pszObjId is %p\n", attr
->pszObjId
);
1806 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
1807 pbEncoded
, cbEncoded
, dwFlags
, NULL
, attr
, pcbStructInfo
, pcbDecoded
,
1808 attr
? attr
->pszObjId
: NULL
);
1811 TRACE("attr->pszObjId is %p (%s)\n", attr
->pszObjId
,
1812 debugstr_a(attr
->pszObjId
));
1813 TRACE("attr->dwValueType is %d\n", attr
->dwValueType
);
1815 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1819 static BOOL
CRYPT_AsnDecodeUnicodeRdn(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1820 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1823 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
1824 CRYPT_AsnDecodeUnicodeRdnAttr
, sizeof(CERT_RDN_ATTR
), TRUE
,
1825 offsetof(CERT_RDN_ATTR
, pszObjId
) };
1826 PCERT_RDN rdn
= (PCERT_RDN
)pvStructInfo
;
1828 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1829 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
1830 rdn
? rdn
->rgRDNAttr
: NULL
);
1834 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType
,
1835 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1836 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1842 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1843 CRYPT_AsnDecodeUnicodeRdn
, sizeof(CERT_RDN
), TRUE
,
1844 offsetof(CERT_RDN
, rgRDNAttr
) };
1846 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1847 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
, NULL
);
1851 SetLastError(STATUS_ACCESS_VIOLATION
);
1858 static BOOL
CRYPT_AsnDecodeCopyBytes(const BYTE
*pbEncoded
,
1859 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1863 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
1865 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1866 pvStructInfo
, *pcbStructInfo
);
1868 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1869 bytesNeeded
+= cbEncoded
;
1871 *pcbDecoded
= cbEncoded
;
1873 *pcbStructInfo
= bytesNeeded
;
1874 else if (*pcbStructInfo
< bytesNeeded
)
1876 SetLastError(ERROR_MORE_DATA
);
1877 *pcbStructInfo
= bytesNeeded
;
1882 PCRYPT_OBJID_BLOB blob
= (PCRYPT_OBJID_BLOB
)pvStructInfo
;
1884 *pcbStructInfo
= bytesNeeded
;
1885 blob
->cbData
= cbEncoded
;
1886 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1887 blob
->pbData
= (LPBYTE
)pbEncoded
;
1890 assert(blob
->pbData
);
1891 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
1897 static BOOL
CRYPT_DecodeDERArray(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1898 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1901 struct AsnArrayDescriptor arrayDesc
= { 0, CRYPT_AsnDecodeCopyBytes
,
1902 sizeof(CRYPT_DER_BLOB
), TRUE
, offsetof(CRYPT_DER_BLOB
, pbData
) };
1903 struct GenericArray
*array
= (struct GenericArray
*)pvStructInfo
;
1905 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
1906 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
1908 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1909 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
1910 array
? array
->rgItems
: NULL
);
1914 static BOOL
CRYPT_AsnDecodePKCSAttributeInternal(const BYTE
*pbEncoded
,
1915 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1919 struct AsnDecodeSequenceItem items
[] = {
1920 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ATTRIBUTE
, pszObjId
),
1921 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1922 offsetof(CRYPT_ATTRIBUTE
, pszObjId
), 0 },
1923 { ASN_CONSTRUCTOR
| ASN_SETOF
, offsetof(CRYPT_ATTRIBUTE
, cValue
),
1924 CRYPT_DecodeDERArray
, sizeof(struct GenericArray
), FALSE
, TRUE
,
1925 offsetof(CRYPT_ATTRIBUTE
, rgValue
), 0 },
1927 PCRYPT_ATTRIBUTE attr
= (PCRYPT_ATTRIBUTE
)pvStructInfo
;
1929 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1930 pvStructInfo
, *pcbStructInfo
);
1932 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
1933 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
1934 pcbDecoded
, attr
? attr
->pszObjId
: NULL
);
1935 TRACE("returning %d\n", ret
);
1939 static BOOL WINAPI
CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType
,
1940 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1941 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1945 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1946 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1952 ret
= CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded
, cbEncoded
,
1953 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
);
1957 *pcbStructInfo
= bytesNeeded
;
1958 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
1959 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
1961 PCRYPT_ATTRIBUTE attr
;
1963 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1964 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1965 attr
= (PCRYPT_ATTRIBUTE
)pvStructInfo
;
1966 attr
->pszObjId
= (LPSTR
)((BYTE
*)pvStructInfo
+
1967 sizeof(CRYPT_ATTRIBUTE
));
1968 ret
= CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded
, cbEncoded
,
1969 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
, &bytesNeeded
,
1976 SetLastError(STATUS_ACCESS_VIOLATION
);
1979 TRACE("returning %d\n", ret
);
1983 static BOOL
CRYPT_AsnDecodePKCSAttributesInternal(const BYTE
*pbEncoded
,
1984 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1987 struct AsnArrayDescriptor arrayDesc
= { 0,
1988 CRYPT_AsnDecodePKCSAttributeInternal
, sizeof(CRYPT_ATTRIBUTE
), TRUE
,
1989 offsetof(CRYPT_ATTRIBUTE
, pszObjId
) };
1990 PCRYPT_ATTRIBUTES attrs
= (PCRYPT_ATTRIBUTES
)pvStructInfo
;
1993 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1994 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
, attrs
? attrs
->rgAttr
:
1999 static BOOL WINAPI
CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType
,
2000 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2001 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2005 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2006 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2013 SetLastError(CRYPT_E_ASN1_EOD
);
2014 else if (pbEncoded
[0] != (ASN_CONSTRUCTOR
| ASN_SETOF
))
2015 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2016 else if ((ret
= CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded
,
2017 cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
,
2021 *pcbStructInfo
= bytesNeeded
;
2022 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2023 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2025 PCRYPT_ATTRIBUTES attrs
;
2027 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2028 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2029 attrs
= (PCRYPT_ATTRIBUTES
)pvStructInfo
;
2030 attrs
->rgAttr
= (PCRYPT_ATTRIBUTE
)((BYTE
*)pvStructInfo
+
2031 sizeof(CRYPT_ATTRIBUTES
));
2032 ret
= CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded
,
2033 cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
2034 &bytesNeeded
, NULL
);
2040 SetLastError(STATUS_ACCESS_VIOLATION
);
2043 TRACE("returning %d\n", ret
);
2047 static BOOL
CRYPT_AsnDecodeAlgorithmId(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2048 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
2050 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
2051 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
2053 struct AsnDecodeSequenceItem items
[] = {
2054 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
2055 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
2056 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
2057 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
2058 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
2059 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
2062 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2063 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2065 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2066 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
2067 pcbDecoded
, algo
? algo
->pszObjId
: NULL
);
2068 if (ret
&& pvStructInfo
)
2070 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
2071 debugstr_a(algo
->pszObjId
));
2076 static BOOL
CRYPT_AsnDecodePubKeyInfoInternal(const BYTE
*pbEncoded
,
2077 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2081 struct AsnDecodeSequenceItem items
[] = {
2082 { ASN_SEQUENCEOF
, offsetof(CERT_PUBLIC_KEY_INFO
, Algorithm
),
2083 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2084 FALSE
, TRUE
, offsetof(CERT_PUBLIC_KEY_INFO
,
2085 Algorithm
.pszObjId
) },
2086 { ASN_BITSTRING
, offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
),
2087 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
2088 offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
.pbData
) },
2090 PCERT_PUBLIC_KEY_INFO info
= (PCERT_PUBLIC_KEY_INFO
)pvStructInfo
;
2092 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2093 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
2094 pcbDecoded
, info
? info
->Algorithm
.Parameters
.pbData
: NULL
);
2098 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
2099 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2100 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2108 if ((ret
= CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded
, cbEncoded
,
2109 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
)))
2112 *pcbStructInfo
= bytesNeeded
;
2113 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2114 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2116 PCERT_PUBLIC_KEY_INFO info
;
2118 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2119 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2120 info
= (PCERT_PUBLIC_KEY_INFO
)pvStructInfo
;
2121 info
->Algorithm
.Parameters
.pbData
= (BYTE
*)pvStructInfo
+
2122 sizeof(CERT_PUBLIC_KEY_INFO
);
2123 ret
= CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded
, cbEncoded
,
2124 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
2125 &bytesNeeded
, NULL
);
2131 SetLastError(STATUS_ACCESS_VIOLATION
);
2138 static BOOL
CRYPT_AsnDecodeBool(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2139 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
2145 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2148 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
2150 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2153 if (pbEncoded
[1] > 1)
2155 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2162 *pcbStructInfo
= sizeof(BOOL
);
2165 else if (*pcbStructInfo
< sizeof(BOOL
))
2167 *pcbStructInfo
= sizeof(BOOL
);
2168 SetLastError(ERROR_MORE_DATA
);
2173 *(BOOL
*)pvStructInfo
= pbEncoded
[2] ? TRUE
: FALSE
;
2176 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2180 static BOOL
CRYPT_AsnDecodeAltNameEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2181 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
2183 PCERT_ALT_NAME_ENTRY entry
= (PCERT_ALT_NAME_ENTRY
)pvStructInfo
;
2184 DWORD dataLen
, lenBytes
, bytesNeeded
= sizeof(CERT_ALT_NAME_ENTRY
);
2187 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2188 pvStructInfo
, *pcbStructInfo
);
2192 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2195 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2196 if (1 + lenBytes
> cbEncoded
)
2198 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2201 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2203 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
2205 case 1: /* rfc822Name */
2206 case 2: /* dNSName */
2207 case 6: /* uniformResourceIdentifier */
2208 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
2210 case 4: /* directoryName */
2211 case 7: /* iPAddress */
2212 bytesNeeded
+= dataLen
;
2214 case 8: /* registeredID */
2215 ret
= CRYPT_AsnDecodeOidIgnoreTag(pbEncoded
, cbEncoded
, 0, NULL
,
2219 /* FIXME: ugly, shouldn't need to know internals of OID decode
2220 * function to use it.
2222 bytesNeeded
+= dataLen
- sizeof(LPSTR
);
2225 case 0: /* otherName */
2226 FIXME("%d: stub\n", pbEncoded
[0] & ASN_TYPE_MASK
);
2227 SetLastError(CRYPT_E_ASN1_BADTAG
);
2230 case 3: /* x400Address, unimplemented */
2231 case 5: /* ediPartyName, unimplemented */
2232 TRACE("type %d unimplemented\n", pbEncoded
[0] & ASN_TYPE_MASK
);
2233 SetLastError(CRYPT_E_ASN1_BADTAG
);
2237 TRACE("type %d bad\n", pbEncoded
[0] & ASN_TYPE_MASK
);
2238 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2244 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
2246 *pcbStructInfo
= bytesNeeded
;
2247 else if (*pcbStructInfo
< bytesNeeded
)
2249 *pcbStructInfo
= bytesNeeded
;
2250 SetLastError(ERROR_MORE_DATA
);
2255 *pcbStructInfo
= bytesNeeded
;
2256 /* MS used values one greater than the asn1 ones.. sigh */
2257 entry
->dwAltNameChoice
= (pbEncoded
[0] & 0x7f) + 1;
2258 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
2260 case 1: /* rfc822Name */
2261 case 2: /* dNSName */
2262 case 6: /* uniformResourceIdentifier */
2266 for (i
= 0; i
< dataLen
; i
++)
2267 entry
->u
.pwszURL
[i
] =
2268 (WCHAR
)pbEncoded
[1 + lenBytes
+ i
];
2269 entry
->u
.pwszURL
[i
] = 0;
2270 TRACE("URL is %p (%s)\n", entry
->u
.pwszURL
,
2271 debugstr_w(entry
->u
.pwszURL
));
2274 case 4: /* directoryName */
2275 entry
->dwAltNameChoice
= CERT_ALT_NAME_DIRECTORY_NAME
;
2276 /* The data are memory-equivalent with the IPAddress case,
2279 case 7: /* iPAddress */
2280 /* The next data pointer is in the pwszURL spot, that is,
2281 * the first 4 bytes. Need to move it to the next spot.
2283 entry
->u
.IPAddress
.pbData
= (LPBYTE
)entry
->u
.pwszURL
;
2284 entry
->u
.IPAddress
.cbData
= dataLen
;
2285 memcpy(entry
->u
.IPAddress
.pbData
, pbEncoded
+ 1 + lenBytes
,
2288 case 8: /* registeredID */
2289 ret
= CRYPT_AsnDecodeOidIgnoreTag(pbEncoded
, cbEncoded
, 0,
2290 &entry
->u
.pszRegisteredID
, &dataLen
, NULL
);
2299 static BOOL
CRYPT_AsnDecodeAltNameInternal(const BYTE
*pbEncoded
,
2300 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2304 struct AsnArrayDescriptor arrayDesc
= { 0,
2305 CRYPT_AsnDecodeAltNameEntry
, sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
2306 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
2307 PCERT_ALT_NAME_INFO info
= (PCERT_ALT_NAME_INFO
)pvStructInfo
;
2309 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2310 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2313 TRACE("info->rgAltEntry is %p\n", info
->rgAltEntry
);
2314 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2315 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
2316 info
? info
->rgAltEntry
: NULL
);
2320 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2321 static BOOL
CRYPT_AsnDecodeIntegerSwapBytes(const BYTE
*pbEncoded
,
2322 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2327 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
2328 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2330 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2333 ret
= CRYPT_AsnDecodeIntegerInternal(pbEncoded
, cbEncoded
,
2334 dwFlags
& ~CRYPT_DECODE_NOCOPY_FLAG
, pvStructInfo
, pcbStructInfo
,
2336 if (ret
&& pvStructInfo
)
2338 CRYPT_DATA_BLOB
*blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2345 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
2347 temp
= blob
->pbData
[i
];
2348 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
2349 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
2353 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2357 static BOOL WINAPI
CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType
,
2358 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2359 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2365 struct AsnDecodeSequenceItem items
[] = {
2366 { ASN_CONTEXT
| 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO
, KeyId
),
2367 CRYPT_AsnDecodeIntegerSwapBytes
, sizeof(CRYPT_DATA_BLOB
),
2368 TRUE
, TRUE
, offsetof(CERT_AUTHORITY_KEY_ID_INFO
, KeyId
.pbData
), 0 },
2369 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1,
2370 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertIssuer
),
2371 CRYPT_AsnDecodeOctetsInternal
, sizeof(CERT_NAME_BLOB
), TRUE
, TRUE
,
2372 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertIssuer
.pbData
), 0 },
2373 { ASN_CONTEXT
| 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO
,
2374 CertSerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2375 sizeof(CRYPT_INTEGER_BLOB
), TRUE
, TRUE
,
2376 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertSerialNumber
.pbData
), 0 },
2379 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2380 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
2381 pcbStructInfo
, NULL
, NULL
);
2385 SetLastError(STATUS_ACCESS_VIOLATION
);
2392 static BOOL WINAPI
CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2393 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2394 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2400 struct AsnDecodeSequenceItem items
[] = {
2401 { ASN_CONTEXT
| 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, KeyId
),
2402 CRYPT_AsnDecodeIntegerSwapBytes
, sizeof(CRYPT_DATA_BLOB
),
2403 TRUE
, TRUE
, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, KeyId
.pbData
), 0 },
2404 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1,
2405 offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, AuthorityCertIssuer
),
2406 CRYPT_AsnDecodeAltNameInternal
, sizeof(CERT_ALT_NAME_INFO
), TRUE
,
2407 TRUE
, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2408 AuthorityCertIssuer
.rgAltEntry
), 0 },
2409 { ASN_CONTEXT
| 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2410 AuthorityCertSerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2411 sizeof(CRYPT_INTEGER_BLOB
), TRUE
, TRUE
,
2412 offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2413 AuthorityCertSerialNumber
.pbData
), 0 },
2416 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2417 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
2418 pcbStructInfo
, NULL
, NULL
);
2422 SetLastError(STATUS_ACCESS_VIOLATION
);
2429 static BOOL
CRYPT_AsnDecodePKCSContent(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2430 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
2435 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2436 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2438 /* The caller has already checked the tag, no need to check it again.
2439 * Check the outer length is valid by calling CRYPT_GetLen:
2441 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2443 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2446 pbEncoded
+= 1 + lenBytes
;
2447 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2448 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &innerLen
)))
2450 ret
= CRYPT_AsnDecodeCopyBytes(pbEncoded
, dataLen
, dwFlags
,
2451 pvStructInfo
, pcbStructInfo
, NULL
);
2453 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
2459 static BOOL
CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE
*pbEncoded
,
2460 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2463 CRYPT_CONTENT_INFO
*info
= (CRYPT_CONTENT_INFO
*)pvStructInfo
;
2464 struct AsnDecodeSequenceItem items
[] = {
2465 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_CONTENT_INFO
, pszObjId
),
2466 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
2467 offsetof(CRYPT_CONTENT_INFO
, pszObjId
), 0 },
2468 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0,
2469 offsetof(CRYPT_CONTENT_INFO
, Content
), CRYPT_AsnDecodePKCSContent
,
2470 sizeof(CRYPT_DER_BLOB
), TRUE
, TRUE
,
2471 offsetof(CRYPT_CONTENT_INFO
, Content
.pbData
), 0 },
2475 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2476 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2478 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2479 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
2480 pcbDecoded
, info
? info
->pszObjId
: NULL
);
2484 static BOOL WINAPI
CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType
,
2485 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2486 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2490 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2491 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2495 ret
= CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded
, cbEncoded
,
2496 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pcbStructInfo
, NULL
);
2497 if (ret
&& pvStructInfo
)
2499 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
2500 pcbStructInfo
, *pcbStructInfo
);
2503 CRYPT_CONTENT_INFO
*info
;
2505 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2506 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2507 info
= (CRYPT_CONTENT_INFO
*)pvStructInfo
;
2508 info
->pszObjId
= (LPSTR
)((BYTE
*)info
+
2509 sizeof(CRYPT_CONTENT_INFO
));
2510 ret
= CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded
,
2511 cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
2512 pcbStructInfo
, NULL
);
2518 SetLastError(STATUS_ACCESS_VIOLATION
);
2524 BOOL
CRYPT_AsnDecodePKCSDigestedData(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2525 DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2526 CRYPT_DIGESTED_DATA
*digestedData
, DWORD
*pcbDigestedData
)
2529 struct AsnDecodeSequenceItem items
[] = {
2530 { ASN_INTEGER
, offsetof(CRYPT_DIGESTED_DATA
, version
),
2531 CRYPT_AsnDecodeIntInternal
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
2532 { ASN_SEQUENCEOF
, offsetof(CRYPT_DIGESTED_DATA
, DigestAlgorithm
),
2533 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2534 FALSE
, TRUE
, offsetof(CRYPT_DIGESTED_DATA
, DigestAlgorithm
.pszObjId
),
2536 { ASN_SEQUENCEOF
, offsetof(CRYPT_DIGESTED_DATA
, ContentInfo
),
2537 CRYPT_AsnDecodePKCSContentInfoInternal
,
2538 sizeof(CRYPT_CONTENT_INFO
), FALSE
, TRUE
, offsetof(CRYPT_DIGESTED_DATA
,
2539 ContentInfo
.pszObjId
), 0 },
2540 { ASN_OCTETSTRING
, offsetof(CRYPT_DIGESTED_DATA
, hash
),
2541 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_HASH_BLOB
), FALSE
, TRUE
,
2542 offsetof(CRYPT_DIGESTED_DATA
, hash
.pbData
), 0 },
2545 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2546 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, digestedData
, pcbDigestedData
,
2551 static BOOL WINAPI
CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType
,
2552 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2553 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2557 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2558 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2564 if ((ret
= CRYPT_AsnDecodeAltNameInternal(pbEncoded
, cbEncoded
,
2565 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
)))
2568 *pcbStructInfo
= bytesNeeded
;
2569 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2570 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2572 CERT_ALT_NAME_INFO
*name
;
2574 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2575 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2576 name
= (CERT_ALT_NAME_INFO
*)pvStructInfo
;
2577 name
->rgAltEntry
= (PCERT_ALT_NAME_ENTRY
)
2578 ((BYTE
*)pvStructInfo
+ sizeof(CERT_ALT_NAME_INFO
));
2579 ret
= CRYPT_AsnDecodeAltNameInternal(pbEncoded
, cbEncoded
,
2580 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
2581 &bytesNeeded
, NULL
);
2587 SetLastError(STATUS_ACCESS_VIOLATION
);
2594 struct PATH_LEN_CONSTRAINT
2596 BOOL fPathLenConstraint
;
2597 DWORD dwPathLenConstraint
;
2600 static BOOL
CRYPT_AsnDecodePathLenConstraint(const BYTE
*pbEncoded
,
2601 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2605 DWORD bytesNeeded
= sizeof(struct PATH_LEN_CONSTRAINT
), size
;
2607 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2608 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2612 ret
= CRYPT_AsnDecodeIntInternal(pbEncoded
, cbEncoded
, dwFlags
, NULL
,
2614 *pcbStructInfo
= bytesNeeded
;
2616 else if (*pcbStructInfo
< bytesNeeded
)
2618 SetLastError(ERROR_MORE_DATA
);
2619 *pcbStructInfo
= bytesNeeded
;
2624 struct PATH_LEN_CONSTRAINT
*constraint
=
2625 (struct PATH_LEN_CONSTRAINT
*)pvStructInfo
;
2627 size
= sizeof(constraint
->dwPathLenConstraint
);
2628 ret
= CRYPT_AsnDecodeIntInternal(pbEncoded
, cbEncoded
, dwFlags
,
2629 &constraint
->dwPathLenConstraint
, &size
, pcbDecoded
);
2631 constraint
->fPathLenConstraint
= TRUE
;
2632 TRACE("got an int, dwPathLenConstraint is %d\n",
2633 constraint
->dwPathLenConstraint
);
2635 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2639 static BOOL
CRYPT_AsnDecodeSubtreeConstraints(const BYTE
*pbEncoded
,
2640 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2644 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
2645 CRYPT_AsnDecodeCopyBytes
, sizeof(CERT_NAME_BLOB
), TRUE
,
2646 offsetof(CERT_NAME_BLOB
, pbData
) };
2647 struct GenericArray
*entries
= (struct GenericArray
*)pvStructInfo
;
2649 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2650 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2652 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2653 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
2654 entries
? entries
->rgItems
: NULL
);
2655 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
2659 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType
,
2660 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2661 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2667 struct AsnDecodeSequenceItem items
[] = {
2668 { ASN_BITSTRING
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
),
2669 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
2670 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
.pbData
), 0 },
2671 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
2672 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
2673 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
2674 { ASN_SEQUENCEOF
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
2675 cSubtreesConstraint
), CRYPT_AsnDecodeSubtreeConstraints
,
2676 sizeof(struct GenericArray
), TRUE
, TRUE
,
2677 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, rgSubtreesConstraint
), 0 },
2680 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2681 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
2682 pcbStructInfo
, NULL
, NULL
);
2686 SetLastError(STATUS_ACCESS_VIOLATION
);
2693 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType
,
2694 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2695 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2701 struct AsnDecodeSequenceItem items
[] = {
2702 { ASN_BOOL
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fCA
),
2703 CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
2704 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
,
2705 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
2706 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
2709 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2710 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
2711 pcbStructInfo
, NULL
, NULL
);
2715 SetLastError(STATUS_ACCESS_VIOLATION
);
2722 #define RSA1_MAGIC 0x31415352
2724 struct DECODED_RSA_PUB_KEY
2727 CRYPT_INTEGER_BLOB modulus
;
2730 static BOOL WINAPI
CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType
,
2731 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2732 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2738 struct AsnDecodeSequenceItem items
[] = {
2739 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
),
2740 CRYPT_AsnDecodeUnsignedIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
),
2741 FALSE
, TRUE
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
.pbData
),
2743 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, pubexp
),
2744 CRYPT_AsnDecodeIntInternal
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
2746 struct DECODED_RSA_PUB_KEY
*decodedKey
= NULL
;
2749 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2750 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &decodedKey
,
2754 DWORD bytesNeeded
= sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) +
2755 decodedKey
->modulus
.cbData
;
2759 *pcbStructInfo
= bytesNeeded
;
2762 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2763 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2766 RSAPUBKEY
*rsaPubKey
;
2768 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2769 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2770 hdr
= (BLOBHEADER
*)pvStructInfo
;
2771 hdr
->bType
= PUBLICKEYBLOB
;
2772 hdr
->bVersion
= CUR_BLOB_VERSION
;
2774 hdr
->aiKeyAlg
= CALG_RSA_KEYX
;
2775 rsaPubKey
= (RSAPUBKEY
*)((BYTE
*)pvStructInfo
+
2776 sizeof(BLOBHEADER
));
2777 rsaPubKey
->magic
= RSA1_MAGIC
;
2778 rsaPubKey
->pubexp
= decodedKey
->pubexp
;
2779 rsaPubKey
->bitlen
= decodedKey
->modulus
.cbData
* 8;
2780 memcpy((BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) +
2781 sizeof(RSAPUBKEY
), decodedKey
->modulus
.pbData
,
2782 decodedKey
->modulus
.cbData
);
2784 LocalFree(decodedKey
);
2789 SetLastError(STATUS_ACCESS_VIOLATION
);
2796 static BOOL
CRYPT_AsnDecodeOctetsInternal(const BYTE
*pbEncoded
,
2797 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2801 DWORD bytesNeeded
, dataLen
;
2803 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2804 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2806 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2808 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2810 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2811 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
2813 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
2815 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
2817 *pcbStructInfo
= bytesNeeded
;
2818 else if (*pcbStructInfo
< bytesNeeded
)
2820 SetLastError(ERROR_MORE_DATA
);
2821 *pcbStructInfo
= bytesNeeded
;
2826 CRYPT_DATA_BLOB
*blob
;
2828 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2829 blob
->cbData
= dataLen
;
2830 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2831 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
2834 assert(blob
->pbData
);
2836 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
2844 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
2845 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2846 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2850 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2851 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2859 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2862 else if (pbEncoded
[0] != ASN_OCTETSTRING
)
2864 SetLastError(CRYPT_E_ASN1_BADTAG
);
2867 else if ((ret
= CRYPT_AsnDecodeOctetsInternal(pbEncoded
, cbEncoded
,
2868 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
)))
2871 *pcbStructInfo
= bytesNeeded
;
2872 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2873 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2875 CRYPT_DATA_BLOB
*blob
;
2877 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2878 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2879 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2880 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_DATA_BLOB
);
2881 ret
= CRYPT_AsnDecodeOctetsInternal(pbEncoded
, cbEncoded
,
2882 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
2883 &bytesNeeded
, NULL
);
2889 SetLastError(STATUS_ACCESS_VIOLATION
);
2896 static BOOL
CRYPT_AsnDecodeBitsInternal(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2897 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
2901 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
2902 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2904 if (pbEncoded
[0] == ASN_BITSTRING
)
2906 DWORD bytesNeeded
, dataLen
;
2907 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2909 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2911 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2912 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
2914 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
2916 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
2918 *pcbStructInfo
= bytesNeeded
;
2919 else if (*pcbStructInfo
< bytesNeeded
)
2921 *pcbStructInfo
= bytesNeeded
;
2922 SetLastError(ERROR_MORE_DATA
);
2927 CRYPT_BIT_BLOB
*blob
;
2929 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2930 blob
->cbData
= dataLen
- 1;
2931 blob
->cUnusedBits
= *(pbEncoded
+ 1 + lenBytes
);
2932 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2934 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 + lenBytes
;
2938 assert(blob
->pbData
);
2941 BYTE mask
= 0xff << blob
->cUnusedBits
;
2943 memcpy(blob
->pbData
, pbEncoded
+ 2 + lenBytes
,
2945 blob
->pbData
[blob
->cbData
- 1] &= mask
;
2953 SetLastError(CRYPT_E_ASN1_BADTAG
);
2956 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2960 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
2961 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2962 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2966 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
2967 pDecodePara
, pvStructInfo
, pcbStructInfo
);
2973 if ((ret
= CRYPT_AsnDecodeBitsInternal(pbEncoded
, cbEncoded
,
2974 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
)))
2977 *pcbStructInfo
= bytesNeeded
;
2978 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2979 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2981 CRYPT_BIT_BLOB
*blob
;
2983 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2984 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2985 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2986 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_BIT_BLOB
);
2987 ret
= CRYPT_AsnDecodeBitsInternal(pbEncoded
, cbEncoded
,
2988 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
2989 &bytesNeeded
, NULL
);
2995 SetLastError(STATUS_ACCESS_VIOLATION
);
2999 TRACE("returning %d (%08x)\n", ret
, GetLastError());
3003 static BOOL
CRYPT_AsnDecodeIntInternal(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3004 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
3007 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
3008 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
3009 DWORD size
= sizeof(buf
);
3011 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
3012 if (pbEncoded
[0] != ASN_INTEGER
)
3014 SetLastError(CRYPT_E_ASN1_BADTAG
);
3018 ret
= CRYPT_AsnDecodeIntegerInternal(pbEncoded
, cbEncoded
, 0, &buf
,
3023 *pcbStructInfo
= sizeof(int);
3024 else if ((ret
= CRYPT_DecodeCheckSpace(pcbStructInfo
, sizeof(int))))
3028 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
3030 /* initialize to a negative value to sign-extend */
3035 for (i
= 0; i
< blob
->cbData
; i
++)
3038 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
3040 memcpy(pvStructInfo
, &val
, sizeof(int));
3043 else if (GetLastError() == ERROR_MORE_DATA
)
3044 SetLastError(CRYPT_E_ASN1_LARGE
);
3048 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
3049 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3050 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3058 ret
= CRYPT_AsnDecodeIntInternal(pbEncoded
, cbEncoded
,
3059 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
);
3063 *pcbStructInfo
= bytesNeeded
;
3064 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3065 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3067 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3068 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3069 ret
= CRYPT_AsnDecodeIntInternal(pbEncoded
, cbEncoded
,
3070 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
3071 &bytesNeeded
, NULL
);
3077 SetLastError(STATUS_ACCESS_VIOLATION
);
3084 static BOOL
CRYPT_AsnDecodeIntegerInternal(const BYTE
*pbEncoded
,
3085 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3089 DWORD bytesNeeded
, dataLen
;
3091 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3093 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3095 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
3097 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
3099 *pcbStructInfo
= bytesNeeded
;
3100 else if (*pcbStructInfo
< bytesNeeded
)
3102 *pcbStructInfo
= bytesNeeded
;
3103 SetLastError(ERROR_MORE_DATA
);
3108 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3110 blob
->cbData
= dataLen
;
3111 assert(blob
->pbData
);
3116 for (i
= 0; i
< blob
->cbData
; i
++)
3118 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
3127 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
3128 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3129 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3137 if (pbEncoded
[0] != ASN_INTEGER
)
3139 SetLastError(CRYPT_E_ASN1_BADTAG
);
3143 ret
= CRYPT_AsnDecodeIntegerInternal(pbEncoded
, cbEncoded
,
3144 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
);
3148 *pcbStructInfo
= bytesNeeded
;
3149 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3150 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3152 CRYPT_INTEGER_BLOB
*blob
;
3154 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3155 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3156 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3157 blob
->pbData
= (BYTE
*)pvStructInfo
+
3158 sizeof(CRYPT_INTEGER_BLOB
);
3159 ret
= CRYPT_AsnDecodeIntegerInternal(pbEncoded
, cbEncoded
,
3160 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, pvStructInfo
,
3161 &bytesNeeded
, NULL
);
3167 SetLastError(STATUS_ACCESS_VIOLATION
);
3174 static BOOL
CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE
*pbEncoded
,
3175 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3180 if (pbEncoded
[0] == ASN_INTEGER
)
3182 DWORD bytesNeeded
, dataLen
;
3184 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3186 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3189 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
3190 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
3192 *pcbStructInfo
= bytesNeeded
;
3193 else if (*pcbStructInfo
< bytesNeeded
)
3195 *pcbStructInfo
= bytesNeeded
;
3196 SetLastError(ERROR_MORE_DATA
);
3201 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3203 blob
->cbData
= dataLen
;
3204 assert(blob
->pbData
);
3205 /* remove leading zero byte if it exists */
3206 if (blob
->cbData
&& *(pbEncoded
+ 1 + lenBytes
) == 0)
3215 for (i
= 0; i
< blob
->cbData
; i
++)
3217 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
3226 SetLastError(CRYPT_E_ASN1_BADTAG
);
3232 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType
,
3233 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3234 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3242 if ((ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded
, cbEncoded
,
3243 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
)))
3246 *pcbStructInfo
= bytesNeeded
;
3247 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3248 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3250 CRYPT_INTEGER_BLOB
*blob
;
3252 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3253 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3254 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3255 blob
->pbData
= (BYTE
*)pvStructInfo
+
3256 sizeof(CRYPT_INTEGER_BLOB
);
3257 ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded
,
3258 cbEncoded
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, pvStructInfo
,
3259 &bytesNeeded
, NULL
);
3265 SetLastError(STATUS_ACCESS_VIOLATION
);
3272 static BOOL WINAPI
CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType
,
3273 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3274 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3280 *pcbStructInfo
= sizeof(int);
3285 if (pbEncoded
[0] == ASN_ENUMERATED
)
3287 unsigned int val
= 0, i
;
3291 SetLastError(CRYPT_E_ASN1_EOD
);
3294 else if (pbEncoded
[1] == 0)
3296 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3301 /* A little strange looking, but we have to accept a sign byte:
3302 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3303 * assuming a small length is okay here, it has to be in short
3306 if (pbEncoded
[1] > sizeof(unsigned int) + 1)
3308 SetLastError(CRYPT_E_ASN1_LARGE
);
3311 for (i
= 0; i
< pbEncoded
[1]; i
++)
3314 val
|= pbEncoded
[2 + i
];
3316 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3317 pvStructInfo
, pcbStructInfo
, sizeof(unsigned int))))
3319 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3320 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3321 memcpy(pvStructInfo
, &val
, sizeof(unsigned int));
3327 SetLastError(CRYPT_E_ASN1_BADTAG
);
3333 SetLastError(STATUS_ACCESS_VIOLATION
);
3340 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3343 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3348 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3350 if (!isdigit(*(pbEncoded))) \
3352 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3358 (word) += *(pbEncoded)++ - '0'; \
3363 static BOOL
CRYPT_AsnDecodeTimeZone(const BYTE
*pbEncoded
, DWORD len
,
3364 SYSTEMTIME
*sysTime
)
3368 if (len
>= 3 && (*pbEncoded
== '+' || *pbEncoded
== '-'))
3370 WORD hours
, minutes
= 0;
3371 BYTE sign
= *pbEncoded
++;
3374 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, hours
);
3375 if (ret
&& hours
>= 24)
3377 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3382 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, minutes
);
3383 if (ret
&& minutes
>= 60)
3385 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3393 sysTime
->wHour
+= hours
;
3394 sysTime
->wMinute
+= minutes
;
3398 if (hours
> sysTime
->wHour
)
3401 sysTime
->wHour
= 24 - (hours
- sysTime
->wHour
);
3404 sysTime
->wHour
-= hours
;
3405 if (minutes
> sysTime
->wMinute
)
3408 sysTime
->wMinute
= 60 - (minutes
- sysTime
->wMinute
);
3411 sysTime
->wMinute
-= minutes
;
3418 #define MIN_ENCODED_TIME_LENGTH 10
3420 static BOOL
CRYPT_AsnDecodeUtcTimeInternal(const BYTE
*pbEncoded
,
3421 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3426 if (pbEncoded
[0] == ASN_UTCTIME
)
3429 SetLastError(CRYPT_E_ASN1_EOD
);
3430 else if (pbEncoded
[1] > 0x7f)
3432 /* long-form date strings really can't be valid */
3433 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3437 SYSTEMTIME sysTime
= { 0 };
3438 BYTE len
= pbEncoded
[1];
3440 if (len
< MIN_ENCODED_TIME_LENGTH
)
3441 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3446 *pcbDecoded
= 2 + len
;
3448 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wYear
);
3449 if (sysTime
.wYear
>= 50)
3450 sysTime
.wYear
+= 1900;
3452 sysTime
.wYear
+= 2000;
3453 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
3454 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
3455 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
3456 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMinute
);
3459 if (len
>= 2 && isdigit(*pbEncoded
) &&
3460 isdigit(*(pbEncoded
+ 1)))
3461 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3463 else if (isdigit(*pbEncoded
))
3464 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 1,
3467 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
3473 *pcbStructInfo
= sizeof(FILETIME
);
3474 else if ((ret
= CRYPT_DecodeCheckSpace(pcbStructInfo
,
3476 ret
= SystemTimeToFileTime(&sysTime
,
3477 (FILETIME
*)pvStructInfo
);
3483 SetLastError(CRYPT_E_ASN1_BADTAG
);
3487 static BOOL WINAPI
CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType
,
3488 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3489 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3497 ret
= CRYPT_AsnDecodeUtcTimeInternal(pbEncoded
, cbEncoded
,
3498 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
);
3502 *pcbStructInfo
= bytesNeeded
;
3503 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3504 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3506 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3507 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3508 ret
= CRYPT_AsnDecodeUtcTimeInternal(pbEncoded
, cbEncoded
,
3509 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
3510 &bytesNeeded
, NULL
);
3516 SetLastError(STATUS_ACCESS_VIOLATION
);
3522 static BOOL
CRYPT_AsnDecodeGeneralizedTime(const BYTE
*pbEncoded
,
3523 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3528 if (pbEncoded
[0] == ASN_GENERALTIME
)
3531 SetLastError(CRYPT_E_ASN1_EOD
);
3532 else if (pbEncoded
[1] > 0x7f)
3534 /* long-form date strings really can't be valid */
3535 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3539 BYTE len
= pbEncoded
[1];
3541 if (len
< MIN_ENCODED_TIME_LENGTH
)
3542 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3545 SYSTEMTIME sysTime
= { 0 };
3549 *pcbDecoded
= 2 + len
;
3551 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 4, sysTime
.wYear
);
3552 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
3553 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
3554 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
3557 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3560 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3562 if (ret
&& len
> 0 && (*pbEncoded
== '.' ||
3569 /* workaround macro weirdness */
3570 digits
= min(len
, 3);
3571 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, digits
,
3572 sysTime
.wMilliseconds
);
3575 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
3581 *pcbStructInfo
= sizeof(FILETIME
);
3582 else if ((ret
= CRYPT_DecodeCheckSpace(pcbStructInfo
,
3584 ret
= SystemTimeToFileTime(&sysTime
,
3585 (FILETIME
*)pvStructInfo
);
3591 SetLastError(CRYPT_E_ASN1_BADTAG
);
3595 static BOOL
CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE
*pbEncoded
,
3596 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3600 InternalDecodeFunc decode
= NULL
;
3602 if (pbEncoded
[0] == ASN_UTCTIME
)
3603 decode
= CRYPT_AsnDecodeUtcTimeInternal
;
3604 else if (pbEncoded
[0] == ASN_GENERALTIME
)
3605 decode
= CRYPT_AsnDecodeGeneralizedTime
;
3607 ret
= decode(pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
,
3608 pcbStructInfo
, pcbDecoded
);
3611 SetLastError(CRYPT_E_ASN1_BADTAG
);
3617 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
3618 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3619 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3627 ret
= CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded
, cbEncoded
,
3628 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
);
3632 *pcbStructInfo
= bytesNeeded
;
3633 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3634 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3636 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3637 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3638 ret
= CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded
, cbEncoded
,
3639 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
3640 &bytesNeeded
, NULL
);
3646 SetLastError(STATUS_ACCESS_VIOLATION
);
3653 static BOOL WINAPI
CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType
,
3654 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3655 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3661 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3663 DWORD bytesNeeded
, dataLen
, remainingLen
, cValue
;
3665 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3670 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3671 bytesNeeded
= sizeof(CRYPT_SEQUENCE_OF_ANY
);
3673 ptr
= pbEncoded
+ 1 + lenBytes
;
3674 remainingLen
= dataLen
;
3675 while (ret
&& remainingLen
)
3679 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
3682 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
3684 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
3685 ptr
+= 1 + nextLenBytes
+ nextLen
;
3686 bytesNeeded
+= sizeof(CRYPT_DER_BLOB
);
3687 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3688 bytesNeeded
+= 1 + nextLenBytes
+ nextLen
;
3694 CRYPT_SEQUENCE_OF_ANY
*seq
;
3698 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3699 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3701 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3702 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3703 seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
3704 seq
->cValue
= cValue
;
3705 seq
->rgValue
= (CRYPT_DER_BLOB
*)((BYTE
*)seq
+
3707 nextPtr
= (BYTE
*)seq
->rgValue
+
3708 cValue
* sizeof(CRYPT_DER_BLOB
);
3709 ptr
= pbEncoded
+ 1 + lenBytes
;
3710 remainingLen
= dataLen
;
3712 while (ret
&& remainingLen
)
3716 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
3719 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
3721 seq
->rgValue
[i
].cbData
= 1 + nextLenBytes
+
3723 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3724 seq
->rgValue
[i
].pbData
= (BYTE
*)ptr
;
3727 seq
->rgValue
[i
].pbData
= nextPtr
;
3728 memcpy(nextPtr
, ptr
, 1 + nextLenBytes
+
3730 nextPtr
+= 1 + nextLenBytes
+ nextLen
;
3732 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
3733 ptr
+= 1 + nextLenBytes
+ nextLen
;
3743 SetLastError(CRYPT_E_ASN1_BADTAG
);
3749 SetLastError(STATUS_ACCESS_VIOLATION
);
3756 static BOOL
CRYPT_AsnDecodeDistPointName(const BYTE
*pbEncoded
,
3757 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3762 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0))
3764 DWORD bytesNeeded
, dataLen
;
3766 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3768 struct AsnArrayDescriptor arrayDesc
= {
3769 ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, CRYPT_AsnDecodeAltNameEntry
,
3770 sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
3771 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
3772 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3778 ret
= CRYPT_AsnDecodeArray(&arrayDesc
,
3779 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
3780 0, NULL
, NULL
, &nameLen
, NULL
, NULL
);
3781 bytesNeeded
= sizeof(CRL_DIST_POINT_NAME
) + nameLen
;
3784 bytesNeeded
= sizeof(CRL_DIST_POINT_NAME
);
3786 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
3788 *pcbStructInfo
= bytesNeeded
;
3789 else if (*pcbStructInfo
< bytesNeeded
)
3791 *pcbStructInfo
= bytesNeeded
;
3792 SetLastError(ERROR_MORE_DATA
);
3797 CRL_DIST_POINT_NAME
*name
= (CRL_DIST_POINT_NAME
*)pvStructInfo
;
3801 name
->dwDistPointNameChoice
= CRL_DIST_POINT_FULL_NAME
;
3802 ret
= CRYPT_AsnDecodeArray(&arrayDesc
,
3803 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
3804 0, NULL
, &name
->u
.FullName
, pcbStructInfo
, NULL
,
3805 name
->u
.FullName
.rgAltEntry
);
3808 name
->dwDistPointNameChoice
= CRL_DIST_POINT_NO_NAME
;
3814 SetLastError(CRYPT_E_ASN1_BADTAG
);
3820 static BOOL
CRYPT_AsnDecodeDistPoint(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3821 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
3823 struct AsnDecodeSequenceItem items
[] = {
3824 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_DIST_POINT
,
3825 DistPointName
), CRYPT_AsnDecodeDistPointName
,
3826 sizeof(CRL_DIST_POINT_NAME
), TRUE
, TRUE
, offsetof(CRL_DIST_POINT
,
3827 DistPointName
.u
.FullName
.rgAltEntry
), 0 },
3828 { ASN_CONTEXT
| 1, offsetof(CRL_DIST_POINT
, ReasonFlags
),
3829 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
3830 offsetof(CRL_DIST_POINT
, ReasonFlags
.pbData
), 0 },
3831 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2, offsetof(CRL_DIST_POINT
, CRLIssuer
),
3832 CRYPT_AsnDecodeAltNameInternal
, sizeof(CERT_ALT_NAME_INFO
), TRUE
, TRUE
,
3833 offsetof(CRL_DIST_POINT
, CRLIssuer
.rgAltEntry
), 0 },
3837 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
3838 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
3843 static BOOL WINAPI
CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType
,
3844 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3845 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3849 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3850 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3854 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3855 CRYPT_AsnDecodeDistPoint
, sizeof(CRL_DIST_POINT
), TRUE
,
3856 offsetof(CRL_DIST_POINT
, DistPointName
.u
.FullName
.rgAltEntry
) };
3858 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3859 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
, NULL
);
3863 SetLastError(STATUS_ACCESS_VIOLATION
);
3870 static BOOL WINAPI
CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3871 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3872 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3876 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3877 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3881 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3882 CRYPT_AsnDecodeOidInternal
, sizeof(LPSTR
), TRUE
, 0 };
3884 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3885 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
, NULL
);
3889 SetLastError(STATUS_ACCESS_VIOLATION
);
3896 static BOOL WINAPI
CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType
,
3897 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3898 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3902 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3903 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3907 struct AsnDecodeSequenceItem items
[] = {
3908 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_ISSUING_DIST_POINT
,
3909 DistPointName
), CRYPT_AsnDecodeDistPointName
,
3910 sizeof(CRL_DIST_POINT_NAME
), TRUE
, TRUE
,
3911 offsetof(CRL_ISSUING_DIST_POINT
,
3912 DistPointName
.u
.FullName
.rgAltEntry
), 0 },
3913 { ASN_CONTEXT
| 1, offsetof(CRL_ISSUING_DIST_POINT
,
3914 fOnlyContainsUserCerts
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
,
3916 { ASN_CONTEXT
| 2, offsetof(CRL_ISSUING_DIST_POINT
,
3917 fOnlyContainsCACerts
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
,
3919 { ASN_CONTEXT
| 3, offsetof(CRL_ISSUING_DIST_POINT
,
3920 OnlySomeReasonFlags
), CRYPT_AsnDecodeBitsInternal
,
3921 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CRL_ISSUING_DIST_POINT
,
3922 OnlySomeReasonFlags
.pbData
), 0 },
3923 { ASN_CONTEXT
| 4, offsetof(CRL_ISSUING_DIST_POINT
,
3924 fIndirectCRL
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
, FALSE
, 0 },
3927 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
3928 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
3929 pcbStructInfo
, NULL
, NULL
);
3933 SetLastError(STATUS_ACCESS_VIOLATION
);
3940 static BOOL
CRYPT_AsnDecodeIssuerSerialNumber(const BYTE
*pbEncoded
,
3941 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3945 struct AsnDecodeSequenceItem items
[] = {
3946 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER
, Issuer
), CRYPT_AsnDecodeDerBlob
,
3947 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_ISSUER_SERIAL_NUMBER
,
3949 { ASN_INTEGER
, offsetof(CERT_ISSUER_SERIAL_NUMBER
, SerialNumber
),
3950 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
,
3951 TRUE
, offsetof(CERT_ISSUER_SERIAL_NUMBER
, SerialNumber
.pbData
), 0 },
3953 CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
=
3954 (CERT_ISSUER_SERIAL_NUMBER
*)pvStructInfo
;
3956 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
3957 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
3959 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
3960 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
3961 pcbDecoded
, issuerSerial
? issuerSerial
->Issuer
.pbData
: NULL
);
3962 if (ret
&& issuerSerial
&& !issuerSerial
->SerialNumber
.cbData
)
3964 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3967 TRACE("returning %d\n", ret
);
3971 static BOOL
CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE
*pbEncoded
,
3972 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3975 CMSG_SIGNER_INFO
*info
= (CMSG_SIGNER_INFO
*)pvStructInfo
;
3976 struct AsnDecodeSequenceItem items
[] = {
3977 { ASN_INTEGER
, offsetof(CMSG_SIGNER_INFO
, dwVersion
),
3978 CRYPT_AsnDecodeIntInternal
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
3979 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, Issuer
),
3980 CRYPT_AsnDecodeIssuerSerialNumber
, sizeof(CERT_ISSUER_SERIAL_NUMBER
),
3981 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, Issuer
.pbData
), 0 },
3982 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, HashAlgorithm
),
3983 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3984 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, HashAlgorithm
.pszObjId
), 0 },
3985 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0,
3986 offsetof(CMSG_SIGNER_INFO
, AuthAttrs
),
3987 CRYPT_AsnDecodePKCSAttributesInternal
, sizeof(CRYPT_ATTRIBUTES
),
3988 TRUE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, AuthAttrs
.rgAttr
), 0 },
3989 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, HashEncryptionAlgorithm
),
3990 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3991 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
,
3992 HashEncryptionAlgorithm
.pszObjId
), 0 },
3993 { ASN_OCTETSTRING
, offsetof(CMSG_SIGNER_INFO
, EncryptedHash
),
3994 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_DER_BLOB
),
3995 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, EncryptedHash
.pbData
), 0 },
3996 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
3997 offsetof(CMSG_SIGNER_INFO
, UnauthAttrs
),
3998 CRYPT_AsnDecodePKCSAttributesInternal
, sizeof(CRYPT_ATTRIBUTES
),
3999 TRUE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, UnauthAttrs
.rgAttr
), 0 },
4003 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
4004 pvStructInfo
, *pcbStructInfo
);
4006 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
4007 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
4008 pcbDecoded
, info
? info
->Issuer
.pbData
: NULL
);
4012 static BOOL WINAPI
CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType
,
4013 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4014 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4018 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
4019 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4023 ret
= CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded
, cbEncoded
,
4024 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pcbStructInfo
, NULL
);
4025 if (ret
&& pvStructInfo
)
4027 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
4028 pcbStructInfo
, *pcbStructInfo
);
4031 CMSG_SIGNER_INFO
*info
;
4033 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4034 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4035 info
= (CMSG_SIGNER_INFO
*)pvStructInfo
;
4036 info
->Issuer
.pbData
= ((BYTE
*)info
+
4037 sizeof(CMSG_SIGNER_INFO
));
4038 ret
= CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded
,
4039 cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
4040 pcbStructInfo
, NULL
);
4046 SetLastError(STATUS_ACCESS_VIOLATION
);
4049 TRACE("returning %d\n", ret
);
4053 static BOOL
CRYPT_DecodeSignerArray(const BYTE
*pbEncoded
, DWORD cbEncoded
,
4054 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
4057 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
4058 CRYPT_AsnDecodePKCSSignerInfoInternal
, sizeof(CMSG_SIGNER_INFO
), TRUE
,
4059 offsetof(CMSG_SIGNER_INFO
, Issuer
.pbData
) };
4060 struct GenericArray
*array
= (struct GenericArray
*)pvStructInfo
;
4062 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
4063 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
4065 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
4066 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
4067 array
? array
->rgItems
: NULL
);
4071 BOOL
CRYPT_AsnDecodePKCSSignedInfo(const BYTE
*pbEncoded
, DWORD cbEncoded
,
4072 DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
4073 CRYPT_SIGNED_INFO
*signedInfo
, DWORD
*pcbSignedInfo
)
4076 struct AsnDecodeSequenceItem items
[] = {
4077 { ASN_INTEGER
, offsetof(CRYPT_SIGNED_INFO
, version
),
4078 CRYPT_AsnDecodeIntInternal
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
4079 /* Placeholder for the hash algorithms - redundant with those in the
4080 * signers, so just ignore them.
4082 { ASN_CONSTRUCTOR
| ASN_SETOF
, 0, NULL
, 0, TRUE
, FALSE
, 0, 0 },
4083 { ASN_SEQUENCE
, offsetof(CRYPT_SIGNED_INFO
, content
),
4084 CRYPT_AsnDecodePKCSContentInfoInternal
, sizeof(CRYPT_CONTENT_INFO
),
4085 FALSE
, TRUE
, offsetof(CRYPT_SIGNED_INFO
, content
.pszObjId
), 0 },
4086 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0,
4087 offsetof(CRYPT_SIGNED_INFO
, cCertEncoded
),
4088 CRYPT_DecodeDERArray
, sizeof(struct GenericArray
), TRUE
, TRUE
,
4089 offsetof(CRYPT_SIGNED_INFO
, rgCertEncoded
), 0 },
4090 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
4091 offsetof(CRYPT_SIGNED_INFO
, cCrlEncoded
), CRYPT_DecodeDERArray
,
4092 sizeof(struct GenericArray
), TRUE
, TRUE
,
4093 offsetof(CRYPT_SIGNED_INFO
, rgCrlEncoded
), 0 },
4094 { ASN_CONSTRUCTOR
| ASN_SETOF
, offsetof(CRYPT_SIGNED_INFO
, cSignerInfo
),
4095 CRYPT_DecodeSignerArray
, sizeof(struct GenericArray
), TRUE
, TRUE
,
4096 offsetof(CRYPT_SIGNED_INFO
, rgSignerInfo
), 0 },
4099 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
4100 pDecodePara
, signedInfo
, *pcbSignedInfo
);
4102 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
4103 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, signedInfo
, pcbSignedInfo
,
4105 TRACE("returning %d\n", ret
);
4109 static CryptDecodeObjectExFunc
CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType
,
4110 LPCSTR lpszStructType
)
4112 CryptDecodeObjectExFunc decodeFunc
= NULL
;
4114 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
4115 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
4117 SetLastError(ERROR_FILE_NOT_FOUND
);
4120 if (!HIWORD(lpszStructType
))
4122 switch (LOWORD(lpszStructType
))
4124 case (WORD
)X509_CERT
:
4125 decodeFunc
= CRYPT_AsnDecodeCertSignedContent
;
4127 case (WORD
)X509_CERT_TO_BE_SIGNED
:
4128 decodeFunc
= CRYPT_AsnDecodeCert
;
4130 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
4131 decodeFunc
= CRYPT_AsnDecodeCRL
;
4133 case (WORD
)X509_EXTENSIONS
:
4134 decodeFunc
= CRYPT_AsnDecodeExtensions
;
4136 case (WORD
)X509_NAME_VALUE
:
4137 decodeFunc
= CRYPT_AsnDecodeNameValue
;
4139 case (WORD
)X509_NAME
:
4140 decodeFunc
= CRYPT_AsnDecodeName
;
4142 case (WORD
)X509_PUBLIC_KEY_INFO
:
4143 decodeFunc
= CRYPT_AsnDecodePubKeyInfo
;
4145 case (WORD
)X509_AUTHORITY_KEY_ID
:
4146 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId
;
4148 case (WORD
)X509_ALTERNATE_NAME
:
4149 decodeFunc
= CRYPT_AsnDecodeAltName
;
4151 case (WORD
)X509_BASIC_CONSTRAINTS
:
4152 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
4154 case (WORD
)X509_BASIC_CONSTRAINTS2
:
4155 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
4157 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
4158 decodeFunc
= CRYPT_AsnDecodeRsaPubKey
;
4160 case (WORD
)X509_UNICODE_NAME
:
4161 decodeFunc
= CRYPT_AsnDecodeUnicodeName
;
4163 case (WORD
)PKCS_ATTRIBUTE
:
4164 decodeFunc
= CRYPT_AsnDecodePKCSAttribute
;
4166 case (WORD
)X509_UNICODE_NAME_VALUE
:
4167 decodeFunc
= CRYPT_AsnDecodeUnicodeNameValue
;
4169 case (WORD
)X509_OCTET_STRING
:
4170 decodeFunc
= CRYPT_AsnDecodeOctets
;
4172 case (WORD
)X509_BITS
:
4173 case (WORD
)X509_KEY_USAGE
:
4174 decodeFunc
= CRYPT_AsnDecodeBits
;
4176 case (WORD
)X509_INTEGER
:
4177 decodeFunc
= CRYPT_AsnDecodeInt
;
4179 case (WORD
)X509_MULTI_BYTE_INTEGER
:
4180 decodeFunc
= CRYPT_AsnDecodeInteger
;
4182 case (WORD
)X509_MULTI_BYTE_UINT
:
4183 decodeFunc
= CRYPT_AsnDecodeUnsignedInteger
;
4185 case (WORD
)X509_ENUMERATED
:
4186 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
4188 case (WORD
)X509_CHOICE_OF_TIME
:
4189 decodeFunc
= CRYPT_AsnDecodeChoiceOfTime
;
4191 case (WORD
)X509_AUTHORITY_KEY_ID2
:
4192 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId2
;
4194 case (WORD
)PKCS_CONTENT_INFO
:
4195 decodeFunc
= CRYPT_AsnDecodePKCSContentInfo
;
4197 case (WORD
)X509_SEQUENCE_OF_ANY
:
4198 decodeFunc
= CRYPT_AsnDecodeSequenceOfAny
;
4200 case (WORD
)PKCS_UTC_TIME
:
4201 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
4203 case (WORD
)X509_CRL_DIST_POINTS
:
4204 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
4206 case (WORD
)X509_ENHANCED_KEY_USAGE
:
4207 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
4209 case (WORD
)PKCS_ATTRIBUTES
:
4210 decodeFunc
= CRYPT_AsnDecodePKCSAttributes
;
4212 case (WORD
)X509_ISSUING_DIST_POINT
:
4213 decodeFunc
= CRYPT_AsnDecodeIssuingDistPoint
;
4215 case (WORD
)PKCS7_SIGNER_INFO
:
4216 decodeFunc
= CRYPT_AsnDecodePKCSSignerInfo
;
4220 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4221 decodeFunc
= CRYPT_AsnDecodeExtensions
;
4222 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4223 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
4224 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4225 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId
;
4226 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4227 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId2
;
4228 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4229 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
4230 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4231 decodeFunc
= CRYPT_AsnDecodeBits
;
4232 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4233 decodeFunc
= CRYPT_AsnDecodeOctets
;
4234 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4235 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
4236 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4237 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
4238 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4239 decodeFunc
= CRYPT_AsnDecodeAltName
;
4240 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4241 decodeFunc
= CRYPT_AsnDecodeAltName
;
4242 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4243 decodeFunc
= CRYPT_AsnDecodeAltName
;
4244 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4245 decodeFunc
= CRYPT_AsnDecodeAltName
;
4246 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4247 decodeFunc
= CRYPT_AsnDecodeAltName
;
4248 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4249 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
4250 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4251 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
4252 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4253 decodeFunc
= CRYPT_AsnDecodeIssuingDistPoint
;
4257 static CryptDecodeObjectFunc
CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType
,
4258 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4260 static HCRYPTOIDFUNCSET set
= NULL
;
4261 CryptDecodeObjectFunc decodeFunc
= NULL
;
4264 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC
, 0);
4265 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4266 (void **)&decodeFunc
, hFunc
);
4270 static CryptDecodeObjectExFunc
CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType
,
4271 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4273 static HCRYPTOIDFUNCSET set
= NULL
;
4274 CryptDecodeObjectExFunc decodeFunc
= NULL
;
4277 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC
, 0);
4278 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4279 (void **)&decodeFunc
, hFunc
);
4283 BOOL WINAPI
CryptDecodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4284 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
,
4285 DWORD
*pcbStructInfo
)
4288 CryptDecodeObjectFunc pCryptDecodeObject
= NULL
;
4289 CryptDecodeObjectExFunc pCryptDecodeObjectEx
= NULL
;
4290 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4292 TRACE_(crypt
)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType
,
4293 debugstr_a(lpszStructType
), pbEncoded
, cbEncoded
, dwFlags
,
4294 pvStructInfo
, pcbStructInfo
);
4296 if (!pvStructInfo
&& !pcbStructInfo
)
4298 SetLastError(ERROR_INVALID_PARAMETER
);
4303 SetLastError(CRYPT_E_ASN1_EOD
);
4306 if (cbEncoded
> MAX_ENCODED_LEN
)
4308 SetLastError(CRYPT_E_ASN1_LARGE
);
4312 if (!(pCryptDecodeObjectEx
= CRYPT_GetBuiltinDecoder(dwCertEncodingType
,
4315 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4316 debugstr_a(lpszStructType
));
4317 pCryptDecodeObject
= CRYPT_LoadDecoderFunc(dwCertEncodingType
,
4318 lpszStructType
, &hFunc
);
4319 if (!pCryptDecodeObject
)
4320 pCryptDecodeObjectEx
= CRYPT_LoadDecoderExFunc(dwCertEncodingType
,
4321 lpszStructType
, &hFunc
);
4323 if (pCryptDecodeObject
)
4324 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
4325 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
4326 else if (pCryptDecodeObjectEx
)
4327 ret
= pCryptDecodeObjectEx(dwCertEncodingType
, lpszStructType
,
4328 pbEncoded
, cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
4329 pvStructInfo
, pcbStructInfo
);
4331 CryptFreeOIDFunctionAddress(hFunc
, 0);
4332 TRACE_(crypt
)("returning %d\n", ret
);
4336 BOOL WINAPI
CryptDecodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4337 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4338 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4341 CryptDecodeObjectExFunc decodeFunc
;
4342 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4344 TRACE_(crypt
)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4345 dwCertEncodingType
, debugstr_a(lpszStructType
), pbEncoded
,
4346 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
4348 if (!pvStructInfo
&& !pcbStructInfo
)
4350 SetLastError(ERROR_INVALID_PARAMETER
);
4355 SetLastError(CRYPT_E_ASN1_EOD
);
4358 if (cbEncoded
> MAX_ENCODED_LEN
)
4360 SetLastError(CRYPT_E_ASN1_LARGE
);
4364 SetLastError(NOERROR
);
4365 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
&& pvStructInfo
)
4366 *(BYTE
**)pvStructInfo
= NULL
;
4367 decodeFunc
= CRYPT_GetBuiltinDecoder(dwCertEncodingType
, lpszStructType
);
4370 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4371 debugstr_a(lpszStructType
));
4372 decodeFunc
= CRYPT_LoadDecoderExFunc(dwCertEncodingType
, lpszStructType
,
4376 ret
= decodeFunc(dwCertEncodingType
, lpszStructType
, pbEncoded
,
4377 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
4380 CryptDecodeObjectFunc pCryptDecodeObject
=
4381 CRYPT_LoadDecoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4383 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4384 * directly, as that could cause an infinite loop.
4386 if (pCryptDecodeObject
)
4388 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4390 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
4391 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pcbStructInfo
);
4392 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4393 pvStructInfo
, pcbStructInfo
, *pcbStructInfo
)))
4394 ret
= pCryptDecodeObject(dwCertEncodingType
,
4395 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
,
4396 *(BYTE
**)pvStructInfo
, pcbStructInfo
);
4399 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
4400 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
4404 CryptFreeOIDFunctionAddress(hFunc
, 0);
4405 TRACE_(crypt
)("returning %d\n", ret
);