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_GetLengthIndefinite(ptr
,
314 cbEncoded
- (ptr
- pbEncoded
), &itemLen
)))
316 BYTE itemLenBytes
= GET_LEN_BYTES(ptr
[1]);
318 if (ptr
[0] == items
[i
].tag
|| !items
[i
].tag
)
320 DWORD itemEncodedLen
;
322 if (itemLen
== CMSG_INDEFINITE_LENGTH
)
323 itemEncodedLen
= cbEncoded
- (ptr
- pbEncoded
);
325 itemEncodedLen
= 1 + itemLenBytes
+ itemLen
;
326 if (nextData
&& pvStructInfo
&& items
[i
].hasPointer
)
328 TRACE("Setting next pointer to %p\n",
330 *(BYTE
**)((BYTE
*)pvStructInfo
+
331 items
[i
].pointerOffset
) = nextData
;
333 if (items
[i
].decodeFunc
)
338 TRACE("decoding item %d\n", i
);
340 TRACE("sizing item %d\n", i
);
341 ret
= items
[i
].decodeFunc(ptr
, itemEncodedLen
,
342 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
,
343 pvStructInfo
? (BYTE
*)pvStructInfo
+ items
[i
].offset
344 : NULL
, &items
[i
].size
, &itemDecoded
);
347 /* Account for alignment padding */
348 if (items
[i
].size
% sizeof(DWORD_PTR
))
349 items
[i
].size
+= sizeof(DWORD_PTR
) -
350 items
[i
].size
% sizeof(DWORD_PTR
);
351 TRACE("item %d size: %d\n", i
, items
[i
].size
);
352 if (nextData
&& items
[i
].hasPointer
&&
353 items
[i
].size
> items
[i
].minSize
)
354 nextData
+= items
[i
].size
- items
[i
].minSize
;
355 if (itemDecoded
> itemEncodedLen
)
357 WARN("decoded length %d exceeds encoded %d\n",
358 itemDecoded
, itemEncodedLen
);
359 SetLastError(CRYPT_E_ASN1_CORRUPT
);
364 if (itemLen
== CMSG_INDEFINITE_LENGTH
)
366 if (itemDecoded
> itemEncodedLen
- 2 ||
367 *(ptr
+ itemDecoded
) != 0 ||
368 *(ptr
+ itemDecoded
+ 1) != 0)
370 TRACE("expected 0 TLV\n");
371 SetLastError(CRYPT_E_ASN1_CORRUPT
);
380 decoded
+= itemDecoded
;
381 TRACE("item %d: decoded %d bytes\n", i
,
386 else if (items
[i
].optional
&&
387 GetLastError() == CRYPT_E_ASN1_BADTAG
)
389 TRACE("skipping optional item %d\n", i
);
390 items
[i
].size
= items
[i
].minSize
;
391 SetLastError(NOERROR
);
395 TRACE("item %d failed: %08x\n", i
,
398 else if (itemLen
== CMSG_INDEFINITE_LENGTH
)
400 ERR("can't use indefinite length encoding without a decoder\n");
401 SetLastError(CRYPT_E_ASN1_CORRUPT
);
406 TRACE("item %d: decoded %d bytes\n", i
, itemEncodedLen
);
407 ptr
+= itemEncodedLen
;
408 decoded
+= itemEncodedLen
;
409 items
[i
].size
= items
[i
].minSize
;
412 else if (items
[i
].optional
)
414 TRACE("skipping optional item %d\n", i
);
415 items
[i
].size
= items
[i
].minSize
;
419 TRACE("item %d: tag %02x doesn't match expected %02x\n",
420 i
, ptr
[0], items
[i
].tag
);
421 SetLastError(CRYPT_E_ASN1_BADTAG
);
426 else if (items
[i
].optional
)
428 TRACE("missing optional item %d, skipping\n", i
);
429 items
[i
].size
= items
[i
].minSize
;
433 TRACE("not enough bytes for item %d, failing\n", i
);
434 SetLastError(CRYPT_E_ASN1_CORRUPT
);
439 *cbDecoded
= decoded
;
440 TRACE("returning %d\n", ret
);
444 /* This decodes an arbitrary sequence into a contiguous block of memory
445 * (basically, a struct.) Each element being decoded is described by a struct
446 * AsnDecodeSequenceItem, see above.
447 * startingPointer is an optional pointer to the first place where dynamic
448 * data will be stored. If you know the starting offset, you may pass it
449 * here. Otherwise, pass NULL, and one will be inferred from the items.
451 static BOOL
CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items
[],
452 DWORD cItem
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
453 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
454 DWORD
*pcbDecoded
, void *startingPointer
)
458 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items
, cItem
, pbEncoded
,
459 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
462 if (pbEncoded
[0] == ASN_SEQUENCE
)
466 if ((ret
= CRYPT_GetLengthIndefinite(pbEncoded
, cbEncoded
, &dataLen
)))
468 DWORD lenBytes
= GET_LEN_BYTES(pbEncoded
[1]), cbDecoded
;
469 const BYTE
*ptr
= pbEncoded
+ 1 + lenBytes
;
470 BOOL indefinite
= FALSE
;
472 cbEncoded
-= 1 + lenBytes
;
473 if (dataLen
== CMSG_INDEFINITE_LENGTH
)
478 else if (cbEncoded
< dataLen
)
480 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen
,
482 SetLastError(CRYPT_E_ASN1_CORRUPT
);
487 ret
= CRYPT_AsnDecodeSequenceItems(items
, cItem
,
488 ptr
, dataLen
, dwFlags
, NULL
, NULL
, &cbDecoded
);
489 if (ret
&& dataLen
== CMSG_INDEFINITE_LENGTH
)
491 if (cbDecoded
> cbEncoded
- 2)
493 /* Not enough space for 0 TLV */
494 SetLastError(CRYPT_E_ASN1_CORRUPT
);
497 else if (*(ptr
+ cbDecoded
) != 0 ||
498 *(ptr
+ cbDecoded
+ 1) != 0)
500 TRACE("expected 0 TLV\n");
501 SetLastError(CRYPT_E_ASN1_CORRUPT
);
508 if (ret
&& !indefinite
&& cbDecoded
!= dataLen
)
510 TRACE("expected %d decoded, got %d, failing\n", dataLen
,
512 SetLastError(CRYPT_E_ASN1_CORRUPT
);
517 DWORD i
, bytesNeeded
= 0, structSize
= 0;
519 for (i
= 0; i
< cItem
; i
++)
521 bytesNeeded
+= items
[i
].size
;
522 structSize
+= items
[i
].minSize
;
525 *pcbDecoded
= 1 + lenBytes
+ cbDecoded
;
527 *pcbStructInfo
= bytesNeeded
;
528 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
529 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
533 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
534 pvStructInfo
= *(BYTE
**)pvStructInfo
;
536 nextData
= (BYTE
*)startingPointer
;
538 nextData
= (BYTE
*)pvStructInfo
+ structSize
;
539 memset(pvStructInfo
, 0, structSize
);
540 ret
= CRYPT_AsnDecodeSequenceItems(items
, cItem
,
541 ptr
, dataLen
, dwFlags
, pvStructInfo
, nextData
,
549 SetLastError(CRYPT_E_ASN1_BADTAG
);
552 TRACE("returning %d (%08x)\n", ret
, GetLastError());
557 * The expected tag of the entire encoded array (usually a variant
558 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
559 * regardless of the tag seen.
561 * used to decode each item in the array
563 * is the minimum size of each decoded item
565 * indicates whether each item has a dynamic pointer
567 * indicates the offset within itemSize at which the pointer exists
569 struct AsnArrayDescriptor
572 InternalDecodeFunc decodeFunc
;
578 struct AsnArrayItemSize
584 /* Decodes an array of like types into a struct GenericArray.
585 * The layout and decoding of the array are described by a struct
586 * AsnArrayDescriptor.
588 static BOOL
CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor
*arrayDesc
,
589 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
590 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
591 DWORD
*pcbDecoded
, void *startingPointer
)
595 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc
, pbEncoded
,
596 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
599 if (!arrayDesc
->tag
|| pbEncoded
[0] == arrayDesc
->tag
)
603 if ((ret
= CRYPT_GetLengthIndefinite(pbEncoded
, cbEncoded
, &dataLen
)))
605 DWORD bytesNeeded
, cItems
= 0, decoded
;
606 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
607 /* There can be arbitrarily many items, but there is often only one.
609 struct AsnArrayItemSize itemSize
= { 0 }, *itemSizes
= &itemSize
;
611 decoded
= 1 + lenBytes
;
612 bytesNeeded
= sizeof(struct GenericArray
);
616 BOOL doneDecoding
= FALSE
;
618 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&& !doneDecoding
; )
622 itemLenBytes
= GET_LEN_BYTES(ptr
[1]);
623 if (dataLen
== CMSG_INDEFINITE_LENGTH
)
628 if (itemLenBytes
!= 1 || ptr
[1] != 0)
630 SetLastError(CRYPT_E_ASN1_CORRUPT
);
637 else if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
)
641 DWORD itemEncoded
, itemDataLen
, itemDecoded
, size
= 0;
643 /* Each item decoded may not tolerate extraneous bytes,
644 * so get the length of the next element if known.
646 if ((ret
= CRYPT_GetLengthIndefinite(ptr
,
647 cbEncoded
- (ptr
- pbEncoded
), &itemDataLen
)))
649 if (itemDataLen
== CMSG_INDEFINITE_LENGTH
)
650 itemEncoded
= cbEncoded
- (ptr
- pbEncoded
);
652 itemEncoded
= 1 + itemLenBytes
+ itemDataLen
;
655 ret
= arrayDesc
->decodeFunc(ptr
, itemEncoded
,
656 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &size
,
661 if (itemSizes
!= &itemSize
)
662 itemSizes
= CryptMemRealloc(itemSizes
,
663 cItems
* sizeof(struct AsnArrayItemSize
));
668 cItems
* sizeof(struct AsnArrayItemSize
));
670 memcpy(itemSizes
, &itemSize
,
675 decoded
+= itemDecoded
;
676 itemSizes
[cItems
- 1].encodedLen
= itemEncoded
;
677 itemSizes
[cItems
- 1].size
= size
;
690 *pcbDecoded
= decoded
;
692 *pcbStructInfo
= bytesNeeded
;
693 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
694 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
699 struct GenericArray
*array
;
701 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
702 pvStructInfo
= *(BYTE
**)pvStructInfo
;
703 array
= (struct GenericArray
*)pvStructInfo
;
704 array
->cItems
= cItems
;
706 array
->rgItems
= startingPointer
;
708 array
->rgItems
= (BYTE
*)array
+
709 sizeof(struct GenericArray
);
710 nextData
= (BYTE
*)array
->rgItems
+
711 array
->cItems
* arrayDesc
->itemSize
;
712 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
713 i
< cItems
&& ptr
- pbEncoded
- 1 - lenBytes
<
718 if (arrayDesc
->hasPointer
)
719 *(BYTE
**)(array
->rgItems
+ i
* arrayDesc
->itemSize
720 + arrayDesc
->pointerOffset
) = nextData
;
721 ret
= arrayDesc
->decodeFunc(ptr
,
722 itemSizes
[i
].encodedLen
,
723 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
,
724 array
->rgItems
+ i
* arrayDesc
->itemSize
,
725 &itemSizes
[i
].size
, &itemDecoded
);
728 nextData
+= itemSizes
[i
].size
- arrayDesc
->itemSize
;
734 if (itemSizes
!= &itemSize
)
735 CryptMemFree(itemSizes
);
740 SetLastError(CRYPT_E_ASN1_BADTAG
);
746 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
747 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
748 * to CRYPT_E_ASN1_CORRUPT.
749 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
752 static BOOL
CRYPT_AsnDecodeDerBlob(const BYTE
*pbEncoded
, DWORD cbEncoded
,
753 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
758 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
760 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
761 DWORD bytesNeeded
= sizeof(CRYPT_DER_BLOB
);
763 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
764 bytesNeeded
+= 1 + lenBytes
+ dataLen
;
767 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
769 *pcbStructInfo
= bytesNeeded
;
770 else if ((ret
= CRYPT_DecodeCheckSpace(pcbStructInfo
, bytesNeeded
)))
772 CRYPT_DER_BLOB
*blob
;
774 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
775 pvStructInfo
= *(BYTE
**)pvStructInfo
;
776 blob
= (CRYPT_DER_BLOB
*)pvStructInfo
;
777 blob
->cbData
= 1 + lenBytes
+ dataLen
;
780 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
781 blob
->pbData
= (BYTE
*)pbEncoded
;
784 assert(blob
->pbData
);
785 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
790 SetLastError(CRYPT_E_ASN1_CORRUPT
);
798 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
799 static BOOL
CRYPT_AsnDecodeBitsSwapBytes(const BYTE
*pbEncoded
,
800 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
805 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
806 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
808 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
811 ret
= CRYPT_AsnDecodeBitsInternal(pbEncoded
, cbEncoded
,
812 dwFlags
& ~CRYPT_DECODE_NOCOPY_FLAG
, pvStructInfo
, pcbStructInfo
,
814 if (ret
&& pvStructInfo
)
816 CRYPT_BIT_BLOB
*blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
823 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
825 temp
= blob
->pbData
[i
];
826 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
827 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
831 TRACE("returning %d (%08x)\n", ret
, GetLastError());
835 static BOOL WINAPI
CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType
,
836 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
837 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
841 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
842 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
846 struct AsnDecodeSequenceItem items
[] = {
847 { 0, offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
),
848 CRYPT_AsnDecodeDerBlob
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
849 offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
.pbData
), 0 },
850 { ASN_SEQUENCEOF
, offsetof(CERT_SIGNED_CONTENT_INFO
,
851 SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
852 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
,
853 offsetof(CERT_SIGNED_CONTENT_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
854 { ASN_BITSTRING
, offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
),
855 CRYPT_AsnDecodeBitsSwapBytes
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
856 offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
.pbData
), 0 },
859 if (dwFlags
& CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
860 items
[2].decodeFunc
= CRYPT_AsnDecodeBitsInternal
;
861 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
862 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
863 pcbStructInfo
, NULL
, NULL
);
867 SetLastError(STATUS_ACCESS_VIOLATION
);
872 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
876 static BOOL
CRYPT_AsnDecodeCertVersion(const BYTE
*pbEncoded
, DWORD cbEncoded
,
877 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
882 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
884 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
886 ret
= CRYPT_AsnDecodeIntInternal(pbEncoded
+ 1 + lenBytes
, dataLen
,
887 dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
889 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
894 static BOOL
CRYPT_AsnDecodeValidity(const BYTE
*pbEncoded
, DWORD cbEncoded
,
895 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
899 struct AsnDecodeSequenceItem items
[] = {
900 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotBefore
),
901 CRYPT_AsnDecodeChoiceOfTimeInternal
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
902 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotAfter
),
903 CRYPT_AsnDecodeChoiceOfTimeInternal
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
906 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
907 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
912 static BOOL
CRYPT_AsnDecodeCertExtensions(const BYTE
*pbEncoded
,
913 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
919 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
921 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
923 ret
= CRYPT_AsnDecodeExtensionsInternal(pbEncoded
+ 1 + lenBytes
,
924 dataLen
, dwFlags
, pvStructInfo
, pcbStructInfo
, NULL
);
925 if (ret
&& pcbDecoded
)
926 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
931 static BOOL WINAPI
CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType
,
932 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
933 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
936 struct AsnDecodeSequenceItem items
[] = {
937 { ASN_CONTEXT
| ASN_CONSTRUCTOR
, offsetof(CERT_INFO
, dwVersion
),
938 CRYPT_AsnDecodeCertVersion
, sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
939 { ASN_INTEGER
, offsetof(CERT_INFO
, SerialNumber
),
940 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
,
941 TRUE
, offsetof(CERT_INFO
, SerialNumber
.pbData
), 0 },
942 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, SignatureAlgorithm
),
943 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
944 FALSE
, TRUE
, offsetof(CERT_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
945 { 0, offsetof(CERT_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
946 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
948 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, NotBefore
),
949 CRYPT_AsnDecodeValidity
, sizeof(CERT_PRIVATE_KEY_VALIDITY
), FALSE
,
951 { 0, offsetof(CERT_INFO
, Subject
), CRYPT_AsnDecodeDerBlob
,
952 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
954 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, SubjectPublicKeyInfo
),
955 CRYPT_AsnDecodePubKeyInfoInternal
, sizeof(CERT_PUBLIC_KEY_INFO
),
956 FALSE
, TRUE
, offsetof(CERT_INFO
,
957 SubjectPublicKeyInfo
.Algorithm
.Parameters
.pbData
), 0 },
958 { ASN_BITSTRING
, offsetof(CERT_INFO
, IssuerUniqueId
),
959 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
960 offsetof(CERT_INFO
, IssuerUniqueId
.pbData
), 0 },
961 { ASN_BITSTRING
, offsetof(CERT_INFO
, SubjectUniqueId
),
962 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
963 offsetof(CERT_INFO
, SubjectUniqueId
.pbData
), 0 },
964 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 3, offsetof(CERT_INFO
, cExtension
),
965 CRYPT_AsnDecodeCertExtensions
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
966 offsetof(CERT_INFO
, rgExtension
), 0 },
969 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
970 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
972 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
973 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
,
975 if (ret
&& pvStructInfo
)
979 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
980 info
= *(CERT_INFO
**)pvStructInfo
;
982 info
= (CERT_INFO
*)pvStructInfo
;
983 if (!info
->SerialNumber
.cbData
|| !info
->Issuer
.cbData
||
984 !info
->Subject
.cbData
)
986 SetLastError(CRYPT_E_ASN1_CORRUPT
);
987 /* Don't need to deallocate, because it should have failed on the
988 * first pass (and no memory was allocated.)
994 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
998 static BOOL WINAPI
CRYPT_AsnDecodeCert(DWORD dwCertEncodingType
,
999 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1000 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1004 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1005 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1011 /* Unless told not to, first try to decode it as a signed cert. */
1012 if (!(dwFlags
& CRYPT_DECODE_TO_BE_SIGNED_FLAG
))
1014 PCERT_SIGNED_CONTENT_INFO signedCert
= NULL
;
1016 ret
= CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType
,
1017 X509_CERT
, pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
1018 (BYTE
*)&signedCert
, &size
);
1022 ret
= CRYPT_AsnDecodeCertInfo(dwCertEncodingType
,
1023 X509_CERT_TO_BE_SIGNED
, signedCert
->ToBeSigned
.pbData
,
1024 signedCert
->ToBeSigned
.cbData
, dwFlags
, pDecodePara
,
1025 pvStructInfo
, pcbStructInfo
);
1026 LocalFree(signedCert
);
1029 /* Failing that, try it as an unsigned cert */
1033 ret
= CRYPT_AsnDecodeCertInfo(dwCertEncodingType
,
1034 X509_CERT_TO_BE_SIGNED
, pbEncoded
, cbEncoded
, dwFlags
,
1035 pDecodePara
, pvStructInfo
, pcbStructInfo
);
1040 SetLastError(STATUS_ACCESS_VIOLATION
);
1044 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
1048 static BOOL
CRYPT_AsnDecodeCRLEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1049 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1052 struct AsnDecodeSequenceItem items
[] = {
1053 { ASN_INTEGER
, offsetof(CRL_ENTRY
, SerialNumber
),
1054 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
,
1055 offsetof(CRL_ENTRY
, SerialNumber
.pbData
), 0 },
1056 { 0, offsetof(CRL_ENTRY
, RevocationDate
),
1057 CRYPT_AsnDecodeChoiceOfTimeInternal
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
1058 { ASN_SEQUENCEOF
, offsetof(CRL_ENTRY
, cExtension
),
1059 CRYPT_AsnDecodeExtensionsInternal
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
1060 offsetof(CRL_ENTRY
, rgExtension
), 0 },
1062 PCRL_ENTRY entry
= (PCRL_ENTRY
)pvStructInfo
;
1064 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
, entry
,
1067 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
1068 pbEncoded
, cbEncoded
, dwFlags
, NULL
, entry
, pcbStructInfo
, pcbDecoded
,
1069 entry
? entry
->SerialNumber
.pbData
: NULL
);
1073 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1074 * been set prior to calling.
1076 static BOOL
CRYPT_AsnDecodeCRLEntries(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1077 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1080 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1081 CRYPT_AsnDecodeCRLEntry
, sizeof(CRL_ENTRY
), TRUE
,
1082 offsetof(CRL_ENTRY
, SerialNumber
.pbData
) };
1083 struct GenericArray
*entries
= (struct GenericArray
*)pvStructInfo
;
1085 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
1086 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
1088 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1089 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
1090 entries
? entries
->rgItems
: NULL
);
1091 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
1095 static BOOL WINAPI
CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType
,
1096 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1097 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1099 struct AsnDecodeSequenceItem items
[] = {
1100 { ASN_INTEGER
, offsetof(CRL_INFO
, dwVersion
),
1101 CRYPT_AsnDecodeIntInternal
, sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
1102 { ASN_SEQUENCEOF
, offsetof(CRL_INFO
, SignatureAlgorithm
),
1103 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
1104 FALSE
, TRUE
, offsetof(CRL_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
1105 { 0, offsetof(CRL_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
1106 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CRL_INFO
,
1108 { 0, offsetof(CRL_INFO
, ThisUpdate
), CRYPT_AsnDecodeChoiceOfTimeInternal
,
1109 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
1110 { 0, offsetof(CRL_INFO
, NextUpdate
), CRYPT_AsnDecodeChoiceOfTimeInternal
,
1111 sizeof(FILETIME
), TRUE
, FALSE
, 0 },
1112 { ASN_SEQUENCEOF
, offsetof(CRL_INFO
, cCRLEntry
),
1113 CRYPT_AsnDecodeCRLEntries
, sizeof(struct GenericArray
), TRUE
, TRUE
,
1114 offsetof(CRL_INFO
, rgCRLEntry
), 0 },
1115 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_INFO
, cExtension
),
1116 CRYPT_AsnDecodeCertExtensions
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
1117 offsetof(CRL_INFO
, rgExtension
), 0 },
1121 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1122 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1124 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
1125 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
,
1128 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
1132 static BOOL WINAPI
CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType
,
1133 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1134 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1138 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1139 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1145 /* Unless told not to, first try to decode it as a signed crl. */
1146 if (!(dwFlags
& CRYPT_DECODE_TO_BE_SIGNED_FLAG
))
1148 PCERT_SIGNED_CONTENT_INFO signedCrl
= NULL
;
1150 ret
= CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType
,
1151 X509_CERT
, pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
1152 (BYTE
*)&signedCrl
, &size
);
1156 ret
= CRYPT_AsnDecodeCRLInfo(dwCertEncodingType
,
1157 X509_CERT_CRL_TO_BE_SIGNED
, signedCrl
->ToBeSigned
.pbData
,
1158 signedCrl
->ToBeSigned
.cbData
, dwFlags
, pDecodePara
,
1159 pvStructInfo
, pcbStructInfo
);
1160 LocalFree(signedCrl
);
1163 /* Failing that, try it as an unsigned crl */
1167 ret
= CRYPT_AsnDecodeCRLInfo(dwCertEncodingType
,
1168 X509_CERT_CRL_TO_BE_SIGNED
, pbEncoded
, cbEncoded
,
1169 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
1174 SetLastError(STATUS_ACCESS_VIOLATION
);
1178 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
1182 static BOOL
CRYPT_AsnDecodeOidIgnoreTag(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1183 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1188 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1189 pvStructInfo
, *pcbStructInfo
);
1191 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1193 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1194 DWORD bytesNeeded
= sizeof(LPSTR
);
1198 /* The largest possible string for the first two components
1199 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1204 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
1205 pbEncoded
[1 + lenBytes
] / 40,
1206 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
1208 bytesNeeded
+= strlen(firstTwo
) + 1;
1209 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1210 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1212 /* large enough for ".4000000" */
1216 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1223 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
1226 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1233 snprintf(str
, sizeof(str
), ".%d", val
);
1234 bytesNeeded
+= strlen(str
);
1239 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
1241 *pcbStructInfo
= bytesNeeded
;
1242 else if (*pcbStructInfo
< bytesNeeded
)
1244 *pcbStructInfo
= bytesNeeded
;
1245 SetLastError(ERROR_MORE_DATA
);
1253 LPSTR pszObjId
= *(LPSTR
*)pvStructInfo
;
1256 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
1257 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
1259 pszObjId
+= strlen(pszObjId
);
1260 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1261 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1265 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1274 sprintf(pszObjId
, ".%d", val
);
1275 pszObjId
+= strlen(pszObjId
);
1279 *(LPSTR
*)pvStructInfo
= NULL
;
1280 *pcbStructInfo
= bytesNeeded
;
1286 static BOOL
CRYPT_AsnDecodeOidInternal(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1287 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1291 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1292 pvStructInfo
, *pcbStructInfo
);
1294 if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
1295 ret
= CRYPT_AsnDecodeOidIgnoreTag(pbEncoded
, cbEncoded
, dwFlags
,
1296 pvStructInfo
, pcbStructInfo
, pcbDecoded
);
1299 SetLastError(CRYPT_E_ASN1_BADTAG
);
1305 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1308 static BOOL
CRYPT_AsnDecodeExtension(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1309 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1311 struct AsnDecodeSequenceItem items
[] = {
1312 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_EXTENSION
, pszObjId
),
1313 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1314 offsetof(CERT_EXTENSION
, pszObjId
), 0 },
1315 { ASN_BOOL
, offsetof(CERT_EXTENSION
, fCritical
), CRYPT_AsnDecodeBool
,
1316 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
1317 { ASN_OCTETSTRING
, offsetof(CERT_EXTENSION
, Value
),
1318 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_OBJID_BLOB
), FALSE
, TRUE
,
1319 offsetof(CERT_EXTENSION
, Value
.pbData
) },
1322 PCERT_EXTENSION ext
= (PCERT_EXTENSION
)pvStructInfo
;
1324 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
, ext
,
1328 TRACE("ext->pszObjId is %p\n", ext
->pszObjId
);
1329 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
1330 pbEncoded
, cbEncoded
, dwFlags
, NULL
, ext
, pcbStructInfo
,
1331 pcbDecoded
, ext
? ext
->pszObjId
: NULL
);
1333 TRACE("ext->pszObjId is %p (%s)\n", ext
->pszObjId
,
1334 debugstr_a(ext
->pszObjId
));
1335 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1339 static BOOL
CRYPT_AsnDecodeExtensionsInternal(const BYTE
*pbEncoded
,
1340 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1344 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1345 CRYPT_AsnDecodeExtension
, sizeof(CERT_EXTENSION
), TRUE
,
1346 offsetof(CERT_EXTENSION
, pszObjId
) };
1347 PCERT_EXTENSIONS exts
= (PCERT_EXTENSIONS
)pvStructInfo
;
1349 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
1350 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
1352 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1353 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
1354 exts
? exts
->rgExtension
: NULL
);
1358 static BOOL WINAPI
CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType
,
1359 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1360 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1366 ret
= CRYPT_AsnDecodeExtensionsInternal(pbEncoded
, cbEncoded
,
1367 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pcbStructInfo
, NULL
);
1368 if (ret
&& pvStructInfo
)
1370 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
1371 pcbStructInfo
, *pcbStructInfo
);
1374 CERT_EXTENSIONS
*exts
;
1376 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1377 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1378 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
1379 exts
->rgExtension
= (CERT_EXTENSION
*)((BYTE
*)exts
+
1380 sizeof(CERT_EXTENSIONS
));
1381 ret
= CRYPT_AsnDecodeExtensionsInternal(pbEncoded
, cbEncoded
,
1382 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
1383 pcbStructInfo
, NULL
);
1389 SetLastError(STATUS_ACCESS_VIOLATION
);
1396 /* Warning: this assumes the address of value->Value.pbData is already set, in
1397 * order to avoid overwriting memory. (In some cases, it may change it, if it
1398 * doesn't copy anything to memory.) Be sure to set it correctly!
1400 static BOOL
CRYPT_AsnDecodeNameValueInternal(const BYTE
*pbEncoded
,
1401 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1406 CERT_NAME_VALUE
*value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1408 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1410 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1411 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
), valueType
;
1413 switch (pbEncoded
[0])
1415 case ASN_OCTETSTRING
:
1416 valueType
= CERT_RDN_OCTET_STRING
;
1417 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1418 bytesNeeded
+= dataLen
;
1420 case ASN_NUMERICSTRING
:
1421 valueType
= CERT_RDN_NUMERIC_STRING
;
1422 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1423 bytesNeeded
+= dataLen
;
1425 case ASN_PRINTABLESTRING
:
1426 valueType
= CERT_RDN_PRINTABLE_STRING
;
1427 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1428 bytesNeeded
+= dataLen
;
1431 valueType
= CERT_RDN_IA5_STRING
;
1432 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1433 bytesNeeded
+= dataLen
;
1436 valueType
= CERT_RDN_T61_STRING
;
1437 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1438 bytesNeeded
+= dataLen
;
1440 case ASN_VIDEOTEXSTRING
:
1441 valueType
= CERT_RDN_VIDEOTEX_STRING
;
1442 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1443 bytesNeeded
+= dataLen
;
1445 case ASN_GRAPHICSTRING
:
1446 valueType
= CERT_RDN_GRAPHIC_STRING
;
1447 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1448 bytesNeeded
+= dataLen
;
1450 case ASN_VISIBLESTRING
:
1451 valueType
= CERT_RDN_VISIBLE_STRING
;
1452 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1453 bytesNeeded
+= dataLen
;
1455 case ASN_GENERALSTRING
:
1456 valueType
= CERT_RDN_GENERAL_STRING
;
1457 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1458 bytesNeeded
+= dataLen
;
1460 case ASN_UNIVERSALSTRING
:
1461 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1462 SetLastError(CRYPT_E_ASN1_BADTAG
);
1465 valueType
= CERT_RDN_BMP_STRING
;
1466 bytesNeeded
+= dataLen
;
1468 case ASN_UTF8STRING
:
1469 valueType
= CERT_RDN_UTF8_STRING
;
1470 bytesNeeded
+= MultiByteToWideChar(CP_UTF8
, 0,
1471 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
, NULL
, 0) * 2;
1474 SetLastError(CRYPT_E_ASN1_BADTAG
);
1479 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
1481 *pcbStructInfo
= bytesNeeded
;
1482 else if (*pcbStructInfo
< bytesNeeded
)
1484 *pcbStructInfo
= bytesNeeded
;
1485 SetLastError(ERROR_MORE_DATA
);
1490 *pcbStructInfo
= bytesNeeded
;
1491 value
->dwValueType
= valueType
;
1496 assert(value
->Value
.pbData
);
1497 switch (pbEncoded
[0])
1499 case ASN_OCTETSTRING
:
1500 case ASN_NUMERICSTRING
:
1501 case ASN_PRINTABLESTRING
:
1504 case ASN_VIDEOTEXSTRING
:
1505 case ASN_GRAPHICSTRING
:
1506 case ASN_VISIBLESTRING
:
1507 case ASN_GENERALSTRING
:
1508 value
->Value
.cbData
= dataLen
;
1511 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1512 memcpy(value
->Value
.pbData
,
1513 pbEncoded
+ 1 + lenBytes
, dataLen
);
1515 value
->Value
.pbData
= (LPBYTE
)pbEncoded
+ 1 +
1521 LPWSTR str
= (LPWSTR
)value
->Value
.pbData
;
1523 value
->Value
.cbData
= dataLen
;
1524 for (i
= 0; i
< dataLen
/ 2; i
++)
1525 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
1526 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
1529 case ASN_UTF8STRING
:
1531 LPWSTR str
= (LPWSTR
)value
->Value
.pbData
;
1533 value
->Value
.cbData
= MultiByteToWideChar(CP_UTF8
, 0,
1534 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
,
1535 str
, bytesNeeded
- sizeof(CERT_NAME_VALUE
)) * 2;
1542 value
->Value
.cbData
= 0;
1543 value
->Value
.pbData
= NULL
;
1550 static BOOL WINAPI
CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType
,
1551 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1552 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1558 ret
= CRYPT_AsnDecodeNameValueInternal(pbEncoded
, cbEncoded
,
1559 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pcbStructInfo
, NULL
);
1560 if (ret
&& pvStructInfo
)
1562 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
1563 pcbStructInfo
, *pcbStructInfo
);
1566 CERT_NAME_VALUE
*value
;
1568 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1569 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1570 value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1571 value
->Value
.pbData
= ((BYTE
*)value
+ sizeof(CERT_NAME_VALUE
));
1572 ret
= CRYPT_AsnDecodeNameValueInternal( pbEncoded
, cbEncoded
,
1573 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
1574 pcbStructInfo
, NULL
);
1580 SetLastError(STATUS_ACCESS_VIOLATION
);
1587 static BOOL
CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE
*pbEncoded
,
1588 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1593 CERT_NAME_VALUE
*value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1595 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1597 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1598 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
), valueType
;
1600 switch (pbEncoded
[0])
1602 case ASN_NUMERICSTRING
:
1603 valueType
= CERT_RDN_NUMERIC_STRING
;
1604 bytesNeeded
+= dataLen
* 2;
1606 case ASN_PRINTABLESTRING
:
1607 valueType
= CERT_RDN_PRINTABLE_STRING
;
1608 bytesNeeded
+= dataLen
* 2;
1611 valueType
= CERT_RDN_IA5_STRING
;
1612 bytesNeeded
+= dataLen
* 2;
1615 valueType
= CERT_RDN_T61_STRING
;
1616 bytesNeeded
+= dataLen
* 2;
1618 case ASN_VIDEOTEXSTRING
:
1619 valueType
= CERT_RDN_VIDEOTEX_STRING
;
1620 bytesNeeded
+= dataLen
* 2;
1622 case ASN_GRAPHICSTRING
:
1623 valueType
= CERT_RDN_GRAPHIC_STRING
;
1624 bytesNeeded
+= dataLen
* 2;
1626 case ASN_VISIBLESTRING
:
1627 valueType
= CERT_RDN_VISIBLE_STRING
;
1628 bytesNeeded
+= dataLen
* 2;
1630 case ASN_GENERALSTRING
:
1631 valueType
= CERT_RDN_GENERAL_STRING
;
1632 bytesNeeded
+= dataLen
* 2;
1634 case ASN_UNIVERSALSTRING
:
1635 valueType
= CERT_RDN_UNIVERSAL_STRING
;
1636 bytesNeeded
+= dataLen
/ 2;
1639 valueType
= CERT_RDN_BMP_STRING
;
1640 bytesNeeded
+= dataLen
;
1642 case ASN_UTF8STRING
:
1643 valueType
= CERT_RDN_UTF8_STRING
;
1644 bytesNeeded
+= MultiByteToWideChar(CP_UTF8
, 0,
1645 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
, NULL
, 0) * 2;
1648 SetLastError(CRYPT_E_ASN1_BADTAG
);
1653 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
1655 *pcbStructInfo
= bytesNeeded
;
1656 else if (*pcbStructInfo
< bytesNeeded
)
1658 *pcbStructInfo
= bytesNeeded
;
1659 SetLastError(ERROR_MORE_DATA
);
1664 *pcbStructInfo
= bytesNeeded
;
1665 value
->dwValueType
= valueType
;
1669 LPWSTR str
= (LPWSTR
)value
->Value
.pbData
;
1671 assert(value
->Value
.pbData
);
1672 switch (pbEncoded
[0])
1674 case ASN_NUMERICSTRING
:
1675 case ASN_PRINTABLESTRING
:
1678 case ASN_VIDEOTEXSTRING
:
1679 case ASN_GRAPHICSTRING
:
1680 case ASN_VISIBLESTRING
:
1681 case ASN_GENERALSTRING
:
1682 value
->Value
.cbData
= dataLen
* 2;
1683 for (i
= 0; i
< dataLen
; i
++)
1684 str
[i
] = pbEncoded
[1 + lenBytes
+ i
];
1686 case ASN_UNIVERSALSTRING
:
1687 value
->Value
.cbData
= dataLen
/ 2;
1688 for (i
= 0; i
< dataLen
/ 4; i
++)
1689 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
+ 2] << 8)
1690 | pbEncoded
[1 + lenBytes
+ 2 * i
+ 3];
1693 value
->Value
.cbData
= dataLen
;
1694 for (i
= 0; i
< dataLen
/ 2; i
++)
1695 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
1696 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
1698 case ASN_UTF8STRING
:
1699 value
->Value
.cbData
= MultiByteToWideChar(CP_UTF8
, 0,
1700 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
,
1701 str
, bytesNeeded
- sizeof(CERT_NAME_VALUE
)) * 2;
1707 value
->Value
.cbData
= 0;
1708 value
->Value
.pbData
= NULL
;
1715 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType
,
1716 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1717 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1723 ret
= CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded
, cbEncoded
,
1724 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pcbStructInfo
, NULL
);
1725 if (ret
&& pvStructInfo
)
1727 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
1728 pcbStructInfo
, *pcbStructInfo
);
1731 CERT_NAME_VALUE
*value
;
1733 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1734 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1735 value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1736 value
->Value
.pbData
= ((BYTE
*)value
+ sizeof(CERT_NAME_VALUE
));
1737 ret
= CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded
,
1738 cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
1739 pcbStructInfo
, NULL
);
1745 SetLastError(STATUS_ACCESS_VIOLATION
);
1752 static BOOL
CRYPT_AsnDecodeRdnAttr(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1753 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1756 struct AsnDecodeSequenceItem items
[] = {
1757 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_RDN_ATTR
, pszObjId
),
1758 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1759 offsetof(CERT_RDN_ATTR
, pszObjId
), 0 },
1760 { 0, offsetof(CERT_RDN_ATTR
, dwValueType
),
1761 CRYPT_AsnDecodeNameValueInternal
, sizeof(CERT_NAME_VALUE
),
1762 FALSE
, TRUE
, offsetof(CERT_RDN_ATTR
, Value
.pbData
), 0 },
1764 CERT_RDN_ATTR
*attr
= (CERT_RDN_ATTR
*)pvStructInfo
;
1766 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1767 pvStructInfo
, *pcbStructInfo
);
1770 TRACE("attr->pszObjId is %p\n", attr
->pszObjId
);
1771 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
1772 pbEncoded
, cbEncoded
, dwFlags
, NULL
, attr
, pcbStructInfo
, pcbDecoded
,
1773 attr
? attr
->pszObjId
: NULL
);
1776 TRACE("attr->pszObjId is %p (%s)\n", attr
->pszObjId
,
1777 debugstr_a(attr
->pszObjId
));
1778 TRACE("attr->dwValueType is %d\n", attr
->dwValueType
);
1780 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1784 static BOOL
CRYPT_AsnDecodeRdn(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1785 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1788 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
1789 CRYPT_AsnDecodeRdnAttr
, sizeof(CERT_RDN_ATTR
), TRUE
,
1790 offsetof(CERT_RDN_ATTR
, pszObjId
) };
1791 PCERT_RDN rdn
= (PCERT_RDN
)pvStructInfo
;
1793 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1794 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
1795 rdn
? rdn
->rgRDNAttr
: NULL
);
1799 static BOOL WINAPI
CRYPT_AsnDecodeName(DWORD dwCertEncodingType
,
1800 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1801 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1807 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1808 CRYPT_AsnDecodeRdn
, sizeof(CERT_RDN
), TRUE
,
1809 offsetof(CERT_RDN
, rgRDNAttr
) };
1811 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1812 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
, NULL
);
1816 SetLastError(STATUS_ACCESS_VIOLATION
);
1823 static BOOL
CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE
*pbEncoded
,
1824 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1828 struct AsnDecodeSequenceItem items
[] = {
1829 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_RDN_ATTR
, pszObjId
),
1830 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1831 offsetof(CERT_RDN_ATTR
, pszObjId
), 0 },
1832 { 0, offsetof(CERT_RDN_ATTR
, dwValueType
),
1833 CRYPT_AsnDecodeUnicodeNameValueInternal
, sizeof(CERT_NAME_VALUE
),
1834 FALSE
, TRUE
, offsetof(CERT_RDN_ATTR
, Value
.pbData
), 0 },
1836 CERT_RDN_ATTR
*attr
= (CERT_RDN_ATTR
*)pvStructInfo
;
1838 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1839 pvStructInfo
, *pcbStructInfo
);
1842 TRACE("attr->pszObjId is %p\n", attr
->pszObjId
);
1843 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
1844 pbEncoded
, cbEncoded
, dwFlags
, NULL
, attr
, pcbStructInfo
, pcbDecoded
,
1845 attr
? attr
->pszObjId
: NULL
);
1848 TRACE("attr->pszObjId is %p (%s)\n", attr
->pszObjId
,
1849 debugstr_a(attr
->pszObjId
));
1850 TRACE("attr->dwValueType is %d\n", attr
->dwValueType
);
1852 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1856 static BOOL
CRYPT_AsnDecodeUnicodeRdn(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1857 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1860 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
1861 CRYPT_AsnDecodeUnicodeRdnAttr
, sizeof(CERT_RDN_ATTR
), TRUE
,
1862 offsetof(CERT_RDN_ATTR
, pszObjId
) };
1863 PCERT_RDN rdn
= (PCERT_RDN
)pvStructInfo
;
1865 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1866 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
1867 rdn
? rdn
->rgRDNAttr
: NULL
);
1871 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType
,
1872 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1873 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1879 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1880 CRYPT_AsnDecodeUnicodeRdn
, sizeof(CERT_RDN
), TRUE
,
1881 offsetof(CERT_RDN
, rgRDNAttr
) };
1883 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1884 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
, NULL
);
1888 SetLastError(STATUS_ACCESS_VIOLATION
);
1895 static BOOL
CRYPT_FindEncodedLen(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1898 BOOL ret
= TRUE
, done
= FALSE
;
1899 DWORD indefiniteNestingLevels
= 0, decoded
= 0;
1901 TRACE("(%p, %d)\n", pbEncoded
, cbEncoded
);
1908 else if ((ret
= CRYPT_GetLengthIndefinite(pbEncoded
, cbEncoded
,
1911 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1913 if (dataLen
== CMSG_INDEFINITE_LENGTH
)
1915 indefiniteNestingLevels
++;
1916 pbEncoded
+= 1 + lenBytes
;
1917 cbEncoded
-= 1 + lenBytes
;
1918 decoded
+= 1 + lenBytes
;
1919 TRACE("indefiniteNestingLevels = %d\n",
1920 indefiniteNestingLevels
);
1924 if (pbEncoded
[0] == 0 && pbEncoded
[1] == 0 &&
1925 indefiniteNestingLevels
)
1927 indefiniteNestingLevels
--;
1928 TRACE("indefiniteNestingLevels = %d\n",
1929 indefiniteNestingLevels
);
1931 pbEncoded
+= 1 + lenBytes
+ dataLen
;
1932 cbEncoded
-= 1 + lenBytes
+ dataLen
;
1933 decoded
+= 1 + lenBytes
+ dataLen
;
1934 if (!indefiniteNestingLevels
)
1938 } while (ret
&& !done
);
1939 /* If we haven't found all 0 TLVs, we haven't found the end */
1940 if (ret
&& indefiniteNestingLevels
)
1942 SetLastError(CRYPT_E_ASN1_EOD
);
1946 *pcbDecoded
= decoded
;
1947 TRACE("returning %d (%d)\n", ret
, ret
? *pcbDecoded
: 0);
1951 static BOOL
CRYPT_AsnDecodeCopyBytes(const BYTE
*pbEncoded
,
1952 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
1956 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
), encodedLen
= 0;
1958 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1959 pvStructInfo
, *pcbStructInfo
);
1961 if ((ret
= CRYPT_FindEncodedLen(pbEncoded
, cbEncoded
, &encodedLen
)))
1963 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1964 bytesNeeded
+= encodedLen
;
1966 *pcbStructInfo
= bytesNeeded
;
1967 else if (*pcbStructInfo
< bytesNeeded
)
1969 SetLastError(ERROR_MORE_DATA
);
1970 *pcbStructInfo
= bytesNeeded
;
1975 PCRYPT_OBJID_BLOB blob
= (PCRYPT_OBJID_BLOB
)pvStructInfo
;
1977 *pcbStructInfo
= bytesNeeded
;
1978 blob
->cbData
= encodedLen
;
1979 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1980 blob
->pbData
= (LPBYTE
)pbEncoded
;
1983 assert(blob
->pbData
);
1984 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
1988 *pcbDecoded
= encodedLen
;
1993 static BOOL
CRYPT_DecodeDERArray(const BYTE
*pbEncoded
, DWORD cbEncoded
,
1994 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
1997 struct AsnArrayDescriptor arrayDesc
= { 0, CRYPT_AsnDecodeCopyBytes
,
1998 sizeof(CRYPT_DER_BLOB
), TRUE
, offsetof(CRYPT_DER_BLOB
, pbData
) };
1999 struct GenericArray
*array
= (struct GenericArray
*)pvStructInfo
;
2001 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2002 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2004 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2005 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
2006 array
? array
->rgItems
: NULL
);
2010 static BOOL
CRYPT_AsnDecodePKCSAttributeInternal(const BYTE
*pbEncoded
,
2011 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2015 struct AsnDecodeSequenceItem items
[] = {
2016 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ATTRIBUTE
, pszObjId
),
2017 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
2018 offsetof(CRYPT_ATTRIBUTE
, pszObjId
), 0 },
2019 { ASN_CONSTRUCTOR
| ASN_SETOF
, offsetof(CRYPT_ATTRIBUTE
, cValue
),
2020 CRYPT_DecodeDERArray
, sizeof(struct GenericArray
), FALSE
, TRUE
,
2021 offsetof(CRYPT_ATTRIBUTE
, rgValue
), 0 },
2023 PCRYPT_ATTRIBUTE attr
= (PCRYPT_ATTRIBUTE
)pvStructInfo
;
2025 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2026 pvStructInfo
, *pcbStructInfo
);
2028 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2029 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
2030 pcbDecoded
, attr
? attr
->pszObjId
: NULL
);
2031 TRACE("returning %d\n", ret
);
2035 static BOOL WINAPI
CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType
,
2036 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2037 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2041 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2042 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2048 ret
= CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded
, cbEncoded
,
2049 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
);
2053 *pcbStructInfo
= bytesNeeded
;
2054 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2055 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2057 PCRYPT_ATTRIBUTE attr
;
2059 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2060 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2061 attr
= (PCRYPT_ATTRIBUTE
)pvStructInfo
;
2062 attr
->pszObjId
= (LPSTR
)((BYTE
*)pvStructInfo
+
2063 sizeof(CRYPT_ATTRIBUTE
));
2064 ret
= CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded
, cbEncoded
,
2065 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
, &bytesNeeded
,
2072 SetLastError(STATUS_ACCESS_VIOLATION
);
2075 TRACE("returning %d\n", ret
);
2079 static BOOL
CRYPT_AsnDecodePKCSAttributesInternal(const BYTE
*pbEncoded
,
2080 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2083 struct AsnArrayDescriptor arrayDesc
= { 0,
2084 CRYPT_AsnDecodePKCSAttributeInternal
, sizeof(CRYPT_ATTRIBUTE
), TRUE
,
2085 offsetof(CRYPT_ATTRIBUTE
, pszObjId
) };
2086 PCRYPT_ATTRIBUTES attrs
= (PCRYPT_ATTRIBUTES
)pvStructInfo
;
2089 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2090 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
, attrs
? attrs
->rgAttr
:
2095 static BOOL WINAPI
CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType
,
2096 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2097 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2101 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2102 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2109 SetLastError(CRYPT_E_ASN1_EOD
);
2110 else if (pbEncoded
[0] != (ASN_CONSTRUCTOR
| ASN_SETOF
))
2111 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2112 else if ((ret
= CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded
,
2113 cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
,
2117 *pcbStructInfo
= bytesNeeded
;
2118 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2119 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2121 PCRYPT_ATTRIBUTES attrs
;
2123 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2124 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2125 attrs
= (PCRYPT_ATTRIBUTES
)pvStructInfo
;
2126 attrs
->rgAttr
= (PCRYPT_ATTRIBUTE
)((BYTE
*)pvStructInfo
+
2127 sizeof(CRYPT_ATTRIBUTES
));
2128 ret
= CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded
,
2129 cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
2130 &bytesNeeded
, NULL
);
2136 SetLastError(STATUS_ACCESS_VIOLATION
);
2139 TRACE("returning %d\n", ret
);
2143 static BOOL
CRYPT_AsnDecodeAlgorithmId(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2144 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
2146 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
2147 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
2149 struct AsnDecodeSequenceItem items
[] = {
2150 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
2151 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
2152 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
2153 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
2154 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
2155 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
2158 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2159 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2161 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2162 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
2163 pcbDecoded
, algo
? algo
->pszObjId
: NULL
);
2164 if (ret
&& pvStructInfo
)
2166 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
2167 debugstr_a(algo
->pszObjId
));
2172 static BOOL
CRYPT_AsnDecodePubKeyInfoInternal(const BYTE
*pbEncoded
,
2173 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2177 struct AsnDecodeSequenceItem items
[] = {
2178 { ASN_SEQUENCEOF
, offsetof(CERT_PUBLIC_KEY_INFO
, Algorithm
),
2179 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2180 FALSE
, TRUE
, offsetof(CERT_PUBLIC_KEY_INFO
,
2181 Algorithm
.pszObjId
) },
2182 { ASN_BITSTRING
, offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
),
2183 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
2184 offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
.pbData
) },
2186 PCERT_PUBLIC_KEY_INFO info
= (PCERT_PUBLIC_KEY_INFO
)pvStructInfo
;
2188 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2189 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
2190 pcbDecoded
, info
? info
->Algorithm
.Parameters
.pbData
: NULL
);
2194 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
2195 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2196 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2204 if ((ret
= CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded
, cbEncoded
,
2205 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
)))
2208 *pcbStructInfo
= bytesNeeded
;
2209 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2210 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2212 PCERT_PUBLIC_KEY_INFO info
;
2214 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2215 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2216 info
= (PCERT_PUBLIC_KEY_INFO
)pvStructInfo
;
2217 info
->Algorithm
.Parameters
.pbData
= (BYTE
*)pvStructInfo
+
2218 sizeof(CERT_PUBLIC_KEY_INFO
);
2219 ret
= CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded
, cbEncoded
,
2220 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
2221 &bytesNeeded
, NULL
);
2227 SetLastError(STATUS_ACCESS_VIOLATION
);
2234 static BOOL
CRYPT_AsnDecodeBool(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2235 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
2241 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2244 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
2246 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2249 if (pbEncoded
[1] > 1)
2251 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2258 *pcbStructInfo
= sizeof(BOOL
);
2261 else if (*pcbStructInfo
< sizeof(BOOL
))
2263 *pcbStructInfo
= sizeof(BOOL
);
2264 SetLastError(ERROR_MORE_DATA
);
2269 *(BOOL
*)pvStructInfo
= pbEncoded
[2] ? TRUE
: FALSE
;
2272 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2276 static BOOL
CRYPT_AsnDecodeAltNameEntry(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2277 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
2279 PCERT_ALT_NAME_ENTRY entry
= (PCERT_ALT_NAME_ENTRY
)pvStructInfo
;
2280 DWORD dataLen
, lenBytes
, bytesNeeded
= sizeof(CERT_ALT_NAME_ENTRY
);
2283 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2284 pvStructInfo
, *pcbStructInfo
);
2288 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2291 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2292 if (1 + lenBytes
> cbEncoded
)
2294 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2297 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2299 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
2301 case 1: /* rfc822Name */
2302 case 2: /* dNSName */
2303 case 6: /* uniformResourceIdentifier */
2304 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
2306 case 4: /* directoryName */
2307 case 7: /* iPAddress */
2308 bytesNeeded
+= dataLen
;
2310 case 8: /* registeredID */
2311 ret
= CRYPT_AsnDecodeOidIgnoreTag(pbEncoded
, cbEncoded
, 0, NULL
,
2315 /* FIXME: ugly, shouldn't need to know internals of OID decode
2316 * function to use it.
2318 bytesNeeded
+= dataLen
- sizeof(LPSTR
);
2321 case 0: /* otherName */
2322 FIXME("%d: stub\n", pbEncoded
[0] & ASN_TYPE_MASK
);
2323 SetLastError(CRYPT_E_ASN1_BADTAG
);
2326 case 3: /* x400Address, unimplemented */
2327 case 5: /* ediPartyName, unimplemented */
2328 TRACE("type %d unimplemented\n", pbEncoded
[0] & ASN_TYPE_MASK
);
2329 SetLastError(CRYPT_E_ASN1_BADTAG
);
2333 TRACE("type %d bad\n", pbEncoded
[0] & ASN_TYPE_MASK
);
2334 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2340 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
2342 *pcbStructInfo
= bytesNeeded
;
2343 else if (*pcbStructInfo
< bytesNeeded
)
2345 *pcbStructInfo
= bytesNeeded
;
2346 SetLastError(ERROR_MORE_DATA
);
2351 *pcbStructInfo
= bytesNeeded
;
2352 /* MS used values one greater than the asn1 ones.. sigh */
2353 entry
->dwAltNameChoice
= (pbEncoded
[0] & 0x7f) + 1;
2354 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
2356 case 1: /* rfc822Name */
2357 case 2: /* dNSName */
2358 case 6: /* uniformResourceIdentifier */
2362 for (i
= 0; i
< dataLen
; i
++)
2363 entry
->u
.pwszURL
[i
] =
2364 (WCHAR
)pbEncoded
[1 + lenBytes
+ i
];
2365 entry
->u
.pwszURL
[i
] = 0;
2366 TRACE("URL is %p (%s)\n", entry
->u
.pwszURL
,
2367 debugstr_w(entry
->u
.pwszURL
));
2370 case 4: /* directoryName */
2371 entry
->dwAltNameChoice
= CERT_ALT_NAME_DIRECTORY_NAME
;
2372 /* The data are memory-equivalent with the IPAddress case,
2375 case 7: /* iPAddress */
2376 /* The next data pointer is in the pwszURL spot, that is,
2377 * the first 4 bytes. Need to move it to the next spot.
2379 entry
->u
.IPAddress
.pbData
= (LPBYTE
)entry
->u
.pwszURL
;
2380 entry
->u
.IPAddress
.cbData
= dataLen
;
2381 memcpy(entry
->u
.IPAddress
.pbData
, pbEncoded
+ 1 + lenBytes
,
2384 case 8: /* registeredID */
2385 ret
= CRYPT_AsnDecodeOidIgnoreTag(pbEncoded
, cbEncoded
, 0,
2386 &entry
->u
.pszRegisteredID
, &dataLen
, NULL
);
2395 static BOOL
CRYPT_AsnDecodeAltNameInternal(const BYTE
*pbEncoded
,
2396 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2400 struct AsnArrayDescriptor arrayDesc
= { 0,
2401 CRYPT_AsnDecodeAltNameEntry
, sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
2402 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
2403 PCERT_ALT_NAME_INFO info
= (PCERT_ALT_NAME_INFO
)pvStructInfo
;
2405 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2406 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2409 TRACE("info->rgAltEntry is %p\n", info
->rgAltEntry
);
2410 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2411 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
2412 info
? info
->rgAltEntry
: NULL
);
2416 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2417 static BOOL
CRYPT_AsnDecodeIntegerSwapBytes(const BYTE
*pbEncoded
,
2418 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2423 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
2424 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2426 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2429 ret
= CRYPT_AsnDecodeIntegerInternal(pbEncoded
, cbEncoded
,
2430 dwFlags
& ~CRYPT_DECODE_NOCOPY_FLAG
, pvStructInfo
, pcbStructInfo
,
2432 if (ret
&& pvStructInfo
)
2434 CRYPT_DATA_BLOB
*blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2441 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
2443 temp
= blob
->pbData
[i
];
2444 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
2445 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
2449 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2453 static BOOL WINAPI
CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType
,
2454 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2455 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2461 struct AsnDecodeSequenceItem items
[] = {
2462 { ASN_CONTEXT
| 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO
, KeyId
),
2463 CRYPT_AsnDecodeIntegerSwapBytes
, sizeof(CRYPT_DATA_BLOB
),
2464 TRUE
, TRUE
, offsetof(CERT_AUTHORITY_KEY_ID_INFO
, KeyId
.pbData
), 0 },
2465 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1,
2466 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertIssuer
),
2467 CRYPT_AsnDecodeOctetsInternal
, sizeof(CERT_NAME_BLOB
), TRUE
, TRUE
,
2468 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertIssuer
.pbData
), 0 },
2469 { ASN_CONTEXT
| 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO
,
2470 CertSerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2471 sizeof(CRYPT_INTEGER_BLOB
), TRUE
, TRUE
,
2472 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertSerialNumber
.pbData
), 0 },
2475 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2476 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
2477 pcbStructInfo
, NULL
, NULL
);
2481 SetLastError(STATUS_ACCESS_VIOLATION
);
2488 static BOOL WINAPI
CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2489 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2490 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2496 struct AsnDecodeSequenceItem items
[] = {
2497 { ASN_CONTEXT
| 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, KeyId
),
2498 CRYPT_AsnDecodeIntegerSwapBytes
, sizeof(CRYPT_DATA_BLOB
),
2499 TRUE
, TRUE
, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, KeyId
.pbData
), 0 },
2500 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1,
2501 offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, AuthorityCertIssuer
),
2502 CRYPT_AsnDecodeAltNameInternal
, sizeof(CERT_ALT_NAME_INFO
), TRUE
,
2503 TRUE
, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2504 AuthorityCertIssuer
.rgAltEntry
), 0 },
2505 { ASN_CONTEXT
| 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2506 AuthorityCertSerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2507 sizeof(CRYPT_INTEGER_BLOB
), TRUE
, TRUE
,
2508 offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2509 AuthorityCertSerialNumber
.pbData
), 0 },
2512 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2513 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
2514 pcbStructInfo
, NULL
, NULL
);
2518 SetLastError(STATUS_ACCESS_VIOLATION
);
2525 static BOOL
CRYPT_AsnDecodePKCSContent(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2526 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
2531 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2532 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2534 /* The caller has already checked the tag, no need to check it again.
2535 * Check the outer length is valid:
2537 if ((ret
= CRYPT_GetLengthIndefinite(pbEncoded
, cbEncoded
, &dataLen
)))
2539 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2542 pbEncoded
+= 1 + lenBytes
;
2543 cbEncoded
-= 1 + lenBytes
;
2544 if (dataLen
== CMSG_INDEFINITE_LENGTH
)
2545 cbEncoded
-= 2; /* space for 0 TLV */
2546 /* Check the inner length is valid: */
2547 if ((ret
= CRYPT_GetLengthIndefinite(pbEncoded
, cbEncoded
, &innerLen
)))
2551 ret
= CRYPT_AsnDecodeCopyBytes(pbEncoded
, cbEncoded
, dwFlags
,
2552 pvStructInfo
, pcbStructInfo
, &decodedLen
);
2553 if (dataLen
== CMSG_INDEFINITE_LENGTH
)
2555 if (*(pbEncoded
+ decodedLen
) != 0 ||
2556 *(pbEncoded
+ decodedLen
+ 1) != 0)
2558 TRACE("expected 0 TLV, got {%02x,%02x}\n",
2559 *(pbEncoded
+ decodedLen
),
2560 *(pbEncoded
+ decodedLen
+ 1));
2561 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2567 if (ret
&& pcbDecoded
)
2569 *pcbDecoded
= 1 + lenBytes
+ decodedLen
;
2570 TRACE("decoded %d bytes\n", *pcbDecoded
);
2577 static BOOL
CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE
*pbEncoded
,
2578 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2581 CRYPT_CONTENT_INFO
*info
= (CRYPT_CONTENT_INFO
*)pvStructInfo
;
2582 struct AsnDecodeSequenceItem items
[] = {
2583 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_CONTENT_INFO
, pszObjId
),
2584 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
2585 offsetof(CRYPT_CONTENT_INFO
, pszObjId
), 0 },
2586 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0,
2587 offsetof(CRYPT_CONTENT_INFO
, Content
), CRYPT_AsnDecodePKCSContent
,
2588 sizeof(CRYPT_DER_BLOB
), TRUE
, TRUE
,
2589 offsetof(CRYPT_CONTENT_INFO
, Content
.pbData
), 0 },
2593 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2594 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2596 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2597 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
2598 pcbDecoded
, info
? info
->pszObjId
: NULL
);
2602 static BOOL WINAPI
CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType
,
2603 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2604 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2608 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2609 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2613 ret
= CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded
, cbEncoded
,
2614 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pcbStructInfo
, NULL
);
2615 if (ret
&& pvStructInfo
)
2617 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
2618 pcbStructInfo
, *pcbStructInfo
);
2621 CRYPT_CONTENT_INFO
*info
;
2623 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2624 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2625 info
= (CRYPT_CONTENT_INFO
*)pvStructInfo
;
2626 info
->pszObjId
= (LPSTR
)((BYTE
*)info
+
2627 sizeof(CRYPT_CONTENT_INFO
));
2628 ret
= CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded
,
2629 cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
2630 pcbStructInfo
, NULL
);
2636 SetLastError(STATUS_ACCESS_VIOLATION
);
2642 BOOL
CRYPT_AsnDecodePKCSDigestedData(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2643 DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2644 CRYPT_DIGESTED_DATA
*digestedData
, DWORD
*pcbDigestedData
)
2647 struct AsnDecodeSequenceItem items
[] = {
2648 { ASN_INTEGER
, offsetof(CRYPT_DIGESTED_DATA
, version
),
2649 CRYPT_AsnDecodeIntInternal
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
2650 { ASN_SEQUENCEOF
, offsetof(CRYPT_DIGESTED_DATA
, DigestAlgorithm
),
2651 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2652 FALSE
, TRUE
, offsetof(CRYPT_DIGESTED_DATA
, DigestAlgorithm
.pszObjId
),
2654 { ASN_SEQUENCEOF
, offsetof(CRYPT_DIGESTED_DATA
, ContentInfo
),
2655 CRYPT_AsnDecodePKCSContentInfoInternal
,
2656 sizeof(CRYPT_CONTENT_INFO
), FALSE
, TRUE
, offsetof(CRYPT_DIGESTED_DATA
,
2657 ContentInfo
.pszObjId
), 0 },
2658 { ASN_OCTETSTRING
, offsetof(CRYPT_DIGESTED_DATA
, hash
),
2659 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_HASH_BLOB
), FALSE
, TRUE
,
2660 offsetof(CRYPT_DIGESTED_DATA
, hash
.pbData
), 0 },
2663 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2664 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, digestedData
, pcbDigestedData
,
2669 static BOOL WINAPI
CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType
,
2670 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2671 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2675 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2676 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2682 if ((ret
= CRYPT_AsnDecodeAltNameInternal(pbEncoded
, cbEncoded
,
2683 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
)))
2686 *pcbStructInfo
= bytesNeeded
;
2687 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2688 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2690 CERT_ALT_NAME_INFO
*name
;
2692 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2693 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2694 name
= (CERT_ALT_NAME_INFO
*)pvStructInfo
;
2695 name
->rgAltEntry
= (PCERT_ALT_NAME_ENTRY
)
2696 ((BYTE
*)pvStructInfo
+ sizeof(CERT_ALT_NAME_INFO
));
2697 ret
= CRYPT_AsnDecodeAltNameInternal(pbEncoded
, cbEncoded
,
2698 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
2699 &bytesNeeded
, NULL
);
2705 SetLastError(STATUS_ACCESS_VIOLATION
);
2712 struct PATH_LEN_CONSTRAINT
2714 BOOL fPathLenConstraint
;
2715 DWORD dwPathLenConstraint
;
2718 static BOOL
CRYPT_AsnDecodePathLenConstraint(const BYTE
*pbEncoded
,
2719 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2723 DWORD bytesNeeded
= sizeof(struct PATH_LEN_CONSTRAINT
), size
;
2725 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2726 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2730 ret
= CRYPT_AsnDecodeIntInternal(pbEncoded
, cbEncoded
, dwFlags
, NULL
,
2732 *pcbStructInfo
= bytesNeeded
;
2734 else if (*pcbStructInfo
< bytesNeeded
)
2736 SetLastError(ERROR_MORE_DATA
);
2737 *pcbStructInfo
= bytesNeeded
;
2742 struct PATH_LEN_CONSTRAINT
*constraint
=
2743 (struct PATH_LEN_CONSTRAINT
*)pvStructInfo
;
2745 size
= sizeof(constraint
->dwPathLenConstraint
);
2746 ret
= CRYPT_AsnDecodeIntInternal(pbEncoded
, cbEncoded
, dwFlags
,
2747 &constraint
->dwPathLenConstraint
, &size
, pcbDecoded
);
2749 constraint
->fPathLenConstraint
= TRUE
;
2750 TRACE("got an int, dwPathLenConstraint is %d\n",
2751 constraint
->dwPathLenConstraint
);
2753 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2757 static BOOL
CRYPT_AsnDecodeSubtreeConstraints(const BYTE
*pbEncoded
,
2758 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2762 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
2763 CRYPT_AsnDecodeCopyBytes
, sizeof(CERT_NAME_BLOB
), TRUE
,
2764 offsetof(CERT_NAME_BLOB
, pbData
) };
2765 struct GenericArray
*entries
= (struct GenericArray
*)pvStructInfo
;
2767 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2768 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2770 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2771 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
2772 entries
? entries
->rgItems
: NULL
);
2773 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
2777 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType
,
2778 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2779 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2785 struct AsnDecodeSequenceItem items
[] = {
2786 { ASN_BITSTRING
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
),
2787 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
2788 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
.pbData
), 0 },
2789 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
2790 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
2791 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
2792 { ASN_SEQUENCEOF
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
2793 cSubtreesConstraint
), CRYPT_AsnDecodeSubtreeConstraints
,
2794 sizeof(struct GenericArray
), TRUE
, TRUE
,
2795 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, rgSubtreesConstraint
), 0 },
2798 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2799 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
2800 pcbStructInfo
, NULL
, NULL
);
2804 SetLastError(STATUS_ACCESS_VIOLATION
);
2811 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType
,
2812 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2813 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2819 struct AsnDecodeSequenceItem items
[] = {
2820 { ASN_BOOL
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fCA
),
2821 CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
2822 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
,
2823 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
2824 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
2827 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2828 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
2829 pcbStructInfo
, NULL
, NULL
);
2833 SetLastError(STATUS_ACCESS_VIOLATION
);
2840 #define RSA1_MAGIC 0x31415352
2842 struct DECODED_RSA_PUB_KEY
2845 CRYPT_INTEGER_BLOB modulus
;
2848 static BOOL WINAPI
CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType
,
2849 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2850 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2856 struct AsnDecodeSequenceItem items
[] = {
2857 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
),
2858 CRYPT_AsnDecodeUnsignedIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
),
2859 FALSE
, TRUE
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
.pbData
),
2861 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, pubexp
),
2862 CRYPT_AsnDecodeIntInternal
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
2864 struct DECODED_RSA_PUB_KEY
*decodedKey
= NULL
;
2867 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
2868 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &decodedKey
,
2872 DWORD bytesNeeded
= sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) +
2873 decodedKey
->modulus
.cbData
;
2877 *pcbStructInfo
= bytesNeeded
;
2880 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2881 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2884 RSAPUBKEY
*rsaPubKey
;
2886 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2887 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2888 hdr
= (BLOBHEADER
*)pvStructInfo
;
2889 hdr
->bType
= PUBLICKEYBLOB
;
2890 hdr
->bVersion
= CUR_BLOB_VERSION
;
2892 hdr
->aiKeyAlg
= CALG_RSA_KEYX
;
2893 rsaPubKey
= (RSAPUBKEY
*)((BYTE
*)pvStructInfo
+
2894 sizeof(BLOBHEADER
));
2895 rsaPubKey
->magic
= RSA1_MAGIC
;
2896 rsaPubKey
->pubexp
= decodedKey
->pubexp
;
2897 rsaPubKey
->bitlen
= decodedKey
->modulus
.cbData
* 8;
2898 memcpy((BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) +
2899 sizeof(RSAPUBKEY
), decodedKey
->modulus
.pbData
,
2900 decodedKey
->modulus
.cbData
);
2902 LocalFree(decodedKey
);
2907 SetLastError(STATUS_ACCESS_VIOLATION
);
2914 static BOOL
CRYPT_AsnDecodeOctetsInternal(const BYTE
*pbEncoded
,
2915 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
2919 DWORD bytesNeeded
, dataLen
;
2921 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
2922 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
2924 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2926 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2928 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2929 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
2931 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
2933 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
2935 *pcbStructInfo
= bytesNeeded
;
2936 else if (*pcbStructInfo
< bytesNeeded
)
2938 SetLastError(ERROR_MORE_DATA
);
2939 *pcbStructInfo
= bytesNeeded
;
2944 CRYPT_DATA_BLOB
*blob
;
2946 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2947 blob
->cbData
= dataLen
;
2948 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2949 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
2952 assert(blob
->pbData
);
2954 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
2962 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
2963 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2964 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2968 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2969 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2977 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2980 else if (pbEncoded
[0] != ASN_OCTETSTRING
)
2982 SetLastError(CRYPT_E_ASN1_BADTAG
);
2985 else if ((ret
= CRYPT_AsnDecodeOctetsInternal(pbEncoded
, cbEncoded
,
2986 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
)))
2989 *pcbStructInfo
= bytesNeeded
;
2990 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2991 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2993 CRYPT_DATA_BLOB
*blob
;
2995 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2996 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2997 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2998 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_DATA_BLOB
);
2999 ret
= CRYPT_AsnDecodeOctetsInternal(pbEncoded
, cbEncoded
,
3000 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
3001 &bytesNeeded
, NULL
);
3007 SetLastError(STATUS_ACCESS_VIOLATION
);
3014 static BOOL
CRYPT_AsnDecodeBitsInternal(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3015 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
3019 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
3020 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
3022 if (pbEncoded
[0] == ASN_BITSTRING
)
3024 DWORD bytesNeeded
, dataLen
;
3025 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3027 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3029 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3030 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
3032 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
3034 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
3036 *pcbStructInfo
= bytesNeeded
;
3037 else if (*pcbStructInfo
< bytesNeeded
)
3039 *pcbStructInfo
= bytesNeeded
;
3040 SetLastError(ERROR_MORE_DATA
);
3045 CRYPT_BIT_BLOB
*blob
;
3047 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
3048 blob
->cbData
= dataLen
- 1;
3049 blob
->cUnusedBits
= *(pbEncoded
+ 1 + lenBytes
);
3050 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3052 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 + lenBytes
;
3056 assert(blob
->pbData
);
3059 BYTE mask
= 0xff << blob
->cUnusedBits
;
3061 memcpy(blob
->pbData
, pbEncoded
+ 2 + lenBytes
,
3063 blob
->pbData
[blob
->cbData
- 1] &= mask
;
3071 SetLastError(CRYPT_E_ASN1_BADTAG
);
3074 TRACE("returning %d (%08x)\n", ret
, GetLastError());
3078 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
3079 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3080 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3084 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
3085 pDecodePara
, pvStructInfo
, pcbStructInfo
);
3091 if ((ret
= CRYPT_AsnDecodeBitsInternal(pbEncoded
, cbEncoded
,
3092 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
)))
3095 *pcbStructInfo
= bytesNeeded
;
3096 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3097 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3099 CRYPT_BIT_BLOB
*blob
;
3101 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3102 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3103 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
3104 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_BIT_BLOB
);
3105 ret
= CRYPT_AsnDecodeBitsInternal(pbEncoded
, cbEncoded
,
3106 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
3107 &bytesNeeded
, NULL
);
3113 SetLastError(STATUS_ACCESS_VIOLATION
);
3117 TRACE("returning %d (%08x)\n", ret
, GetLastError());
3121 static BOOL
CRYPT_AsnDecodeIntInternal(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3122 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
3125 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
3126 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
3127 DWORD size
= sizeof(buf
);
3129 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
3130 if (pbEncoded
[0] != ASN_INTEGER
)
3132 SetLastError(CRYPT_E_ASN1_BADTAG
);
3136 ret
= CRYPT_AsnDecodeIntegerInternal(pbEncoded
, cbEncoded
, 0, &buf
,
3141 *pcbStructInfo
= sizeof(int);
3142 else if ((ret
= CRYPT_DecodeCheckSpace(pcbStructInfo
, sizeof(int))))
3146 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
3148 /* initialize to a negative value to sign-extend */
3153 for (i
= 0; i
< blob
->cbData
; i
++)
3156 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
3158 memcpy(pvStructInfo
, &val
, sizeof(int));
3161 else if (GetLastError() == ERROR_MORE_DATA
)
3162 SetLastError(CRYPT_E_ASN1_LARGE
);
3166 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
3167 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3168 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3176 ret
= CRYPT_AsnDecodeIntInternal(pbEncoded
, cbEncoded
,
3177 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
);
3181 *pcbStructInfo
= bytesNeeded
;
3182 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3183 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3185 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3186 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3187 ret
= CRYPT_AsnDecodeIntInternal(pbEncoded
, cbEncoded
,
3188 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
3189 &bytesNeeded
, NULL
);
3195 SetLastError(STATUS_ACCESS_VIOLATION
);
3202 static BOOL
CRYPT_AsnDecodeIntegerInternal(const BYTE
*pbEncoded
,
3203 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3207 DWORD bytesNeeded
, dataLen
;
3209 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3211 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3213 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
3215 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
3217 *pcbStructInfo
= bytesNeeded
;
3218 else if (*pcbStructInfo
< bytesNeeded
)
3220 *pcbStructInfo
= bytesNeeded
;
3221 SetLastError(ERROR_MORE_DATA
);
3226 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3228 blob
->cbData
= dataLen
;
3229 assert(blob
->pbData
);
3234 for (i
= 0; i
< blob
->cbData
; i
++)
3236 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
3245 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
3246 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3247 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3255 if (pbEncoded
[0] != ASN_INTEGER
)
3257 SetLastError(CRYPT_E_ASN1_BADTAG
);
3261 ret
= CRYPT_AsnDecodeIntegerInternal(pbEncoded
, cbEncoded
,
3262 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
);
3266 *pcbStructInfo
= bytesNeeded
;
3267 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3268 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3270 CRYPT_INTEGER_BLOB
*blob
;
3272 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3273 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3274 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3275 blob
->pbData
= (BYTE
*)pvStructInfo
+
3276 sizeof(CRYPT_INTEGER_BLOB
);
3277 ret
= CRYPT_AsnDecodeIntegerInternal(pbEncoded
, cbEncoded
,
3278 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, pvStructInfo
,
3279 &bytesNeeded
, NULL
);
3285 SetLastError(STATUS_ACCESS_VIOLATION
);
3292 static BOOL
CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE
*pbEncoded
,
3293 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3298 if (pbEncoded
[0] == ASN_INTEGER
)
3300 DWORD bytesNeeded
, dataLen
;
3302 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3304 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3307 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
3308 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
3310 *pcbStructInfo
= bytesNeeded
;
3311 else if (*pcbStructInfo
< bytesNeeded
)
3313 *pcbStructInfo
= bytesNeeded
;
3314 SetLastError(ERROR_MORE_DATA
);
3319 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3321 blob
->cbData
= dataLen
;
3322 assert(blob
->pbData
);
3323 /* remove leading zero byte if it exists */
3324 if (blob
->cbData
&& *(pbEncoded
+ 1 + lenBytes
) == 0)
3333 for (i
= 0; i
< blob
->cbData
; i
++)
3335 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
3344 SetLastError(CRYPT_E_ASN1_BADTAG
);
3350 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType
,
3351 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3352 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3360 if ((ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded
, cbEncoded
,
3361 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
)))
3364 *pcbStructInfo
= bytesNeeded
;
3365 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3366 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3368 CRYPT_INTEGER_BLOB
*blob
;
3370 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3371 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3372 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3373 blob
->pbData
= (BYTE
*)pvStructInfo
+
3374 sizeof(CRYPT_INTEGER_BLOB
);
3375 ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded
,
3376 cbEncoded
, dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, pvStructInfo
,
3377 &bytesNeeded
, NULL
);
3383 SetLastError(STATUS_ACCESS_VIOLATION
);
3390 static BOOL WINAPI
CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType
,
3391 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3392 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3398 *pcbStructInfo
= sizeof(int);
3403 if (pbEncoded
[0] == ASN_ENUMERATED
)
3405 unsigned int val
= 0, i
;
3409 SetLastError(CRYPT_E_ASN1_EOD
);
3412 else if (pbEncoded
[1] == 0)
3414 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3419 /* A little strange looking, but we have to accept a sign byte:
3420 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3421 * assuming a small length is okay here, it has to be in short
3424 if (pbEncoded
[1] > sizeof(unsigned int) + 1)
3426 SetLastError(CRYPT_E_ASN1_LARGE
);
3429 for (i
= 0; i
< pbEncoded
[1]; i
++)
3432 val
|= pbEncoded
[2 + i
];
3434 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3435 pvStructInfo
, pcbStructInfo
, sizeof(unsigned int))))
3437 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3438 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3439 memcpy(pvStructInfo
, &val
, sizeof(unsigned int));
3445 SetLastError(CRYPT_E_ASN1_BADTAG
);
3451 SetLastError(STATUS_ACCESS_VIOLATION
);
3458 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3461 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3466 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3468 if (!isdigit(*(pbEncoded))) \
3470 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3476 (word) += *(pbEncoded)++ - '0'; \
3481 static BOOL
CRYPT_AsnDecodeTimeZone(const BYTE
*pbEncoded
, DWORD len
,
3482 SYSTEMTIME
*sysTime
)
3486 if (len
>= 3 && (*pbEncoded
== '+' || *pbEncoded
== '-'))
3488 WORD hours
, minutes
= 0;
3489 BYTE sign
= *pbEncoded
++;
3492 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, hours
);
3493 if (ret
&& hours
>= 24)
3495 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3500 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, minutes
);
3501 if (ret
&& minutes
>= 60)
3503 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3511 sysTime
->wHour
+= hours
;
3512 sysTime
->wMinute
+= minutes
;
3516 if (hours
> sysTime
->wHour
)
3519 sysTime
->wHour
= 24 - (hours
- sysTime
->wHour
);
3522 sysTime
->wHour
-= hours
;
3523 if (minutes
> sysTime
->wMinute
)
3526 sysTime
->wMinute
= 60 - (minutes
- sysTime
->wMinute
);
3529 sysTime
->wMinute
-= minutes
;
3536 #define MIN_ENCODED_TIME_LENGTH 10
3538 static BOOL
CRYPT_AsnDecodeUtcTimeInternal(const BYTE
*pbEncoded
,
3539 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3544 if (pbEncoded
[0] == ASN_UTCTIME
)
3547 SetLastError(CRYPT_E_ASN1_EOD
);
3548 else if (pbEncoded
[1] > 0x7f)
3550 /* long-form date strings really can't be valid */
3551 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3555 SYSTEMTIME sysTime
= { 0 };
3556 BYTE len
= pbEncoded
[1];
3558 if (len
< MIN_ENCODED_TIME_LENGTH
)
3559 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3564 *pcbDecoded
= 2 + len
;
3566 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wYear
);
3567 if (sysTime
.wYear
>= 50)
3568 sysTime
.wYear
+= 1900;
3570 sysTime
.wYear
+= 2000;
3571 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
3572 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
3573 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
3574 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMinute
);
3577 if (len
>= 2 && isdigit(*pbEncoded
) &&
3578 isdigit(*(pbEncoded
+ 1)))
3579 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3581 else if (isdigit(*pbEncoded
))
3582 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 1,
3585 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
3591 *pcbStructInfo
= sizeof(FILETIME
);
3592 else if ((ret
= CRYPT_DecodeCheckSpace(pcbStructInfo
,
3594 ret
= SystemTimeToFileTime(&sysTime
,
3595 (FILETIME
*)pvStructInfo
);
3601 SetLastError(CRYPT_E_ASN1_BADTAG
);
3605 static BOOL WINAPI
CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType
,
3606 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3607 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3615 ret
= CRYPT_AsnDecodeUtcTimeInternal(pbEncoded
, cbEncoded
,
3616 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
);
3620 *pcbStructInfo
= bytesNeeded
;
3621 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3622 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3624 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3625 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3626 ret
= CRYPT_AsnDecodeUtcTimeInternal(pbEncoded
, cbEncoded
,
3627 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
3628 &bytesNeeded
, NULL
);
3634 SetLastError(STATUS_ACCESS_VIOLATION
);
3640 static BOOL
CRYPT_AsnDecodeGeneralizedTime(const BYTE
*pbEncoded
,
3641 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3646 if (pbEncoded
[0] == ASN_GENERALTIME
)
3649 SetLastError(CRYPT_E_ASN1_EOD
);
3650 else if (pbEncoded
[1] > 0x7f)
3652 /* long-form date strings really can't be valid */
3653 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3657 BYTE len
= pbEncoded
[1];
3659 if (len
< MIN_ENCODED_TIME_LENGTH
)
3660 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3663 SYSTEMTIME sysTime
= { 0 };
3667 *pcbDecoded
= 2 + len
;
3669 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 4, sysTime
.wYear
);
3670 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
3671 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
3672 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
3675 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3678 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3680 if (ret
&& len
> 0 && (*pbEncoded
== '.' ||
3687 /* workaround macro weirdness */
3688 digits
= min(len
, 3);
3689 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, digits
,
3690 sysTime
.wMilliseconds
);
3693 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
3699 *pcbStructInfo
= sizeof(FILETIME
);
3700 else if ((ret
= CRYPT_DecodeCheckSpace(pcbStructInfo
,
3702 ret
= SystemTimeToFileTime(&sysTime
,
3703 (FILETIME
*)pvStructInfo
);
3709 SetLastError(CRYPT_E_ASN1_BADTAG
);
3713 static BOOL
CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE
*pbEncoded
,
3714 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3718 InternalDecodeFunc decode
= NULL
;
3720 if (pbEncoded
[0] == ASN_UTCTIME
)
3721 decode
= CRYPT_AsnDecodeUtcTimeInternal
;
3722 else if (pbEncoded
[0] == ASN_GENERALTIME
)
3723 decode
= CRYPT_AsnDecodeGeneralizedTime
;
3725 ret
= decode(pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
,
3726 pcbStructInfo
, pcbDecoded
);
3729 SetLastError(CRYPT_E_ASN1_BADTAG
);
3735 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
3736 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3737 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3745 ret
= CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded
, cbEncoded
,
3746 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bytesNeeded
, NULL
);
3750 *pcbStructInfo
= bytesNeeded
;
3751 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3752 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3754 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3755 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3756 ret
= CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded
, cbEncoded
,
3757 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
3758 &bytesNeeded
, NULL
);
3764 SetLastError(STATUS_ACCESS_VIOLATION
);
3771 static BOOL WINAPI
CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType
,
3772 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3773 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3779 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3781 DWORD bytesNeeded
, dataLen
, remainingLen
, cValue
;
3783 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3788 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3789 bytesNeeded
= sizeof(CRYPT_SEQUENCE_OF_ANY
);
3791 ptr
= pbEncoded
+ 1 + lenBytes
;
3792 remainingLen
= dataLen
;
3793 while (ret
&& remainingLen
)
3797 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
3800 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
3802 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
3803 ptr
+= 1 + nextLenBytes
+ nextLen
;
3804 bytesNeeded
+= sizeof(CRYPT_DER_BLOB
);
3805 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3806 bytesNeeded
+= 1 + nextLenBytes
+ nextLen
;
3812 CRYPT_SEQUENCE_OF_ANY
*seq
;
3816 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3817 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3819 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3820 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3821 seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
3822 seq
->cValue
= cValue
;
3823 seq
->rgValue
= (CRYPT_DER_BLOB
*)((BYTE
*)seq
+
3825 nextPtr
= (BYTE
*)seq
->rgValue
+
3826 cValue
* sizeof(CRYPT_DER_BLOB
);
3827 ptr
= pbEncoded
+ 1 + lenBytes
;
3828 remainingLen
= dataLen
;
3830 while (ret
&& remainingLen
)
3834 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
3837 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
3839 seq
->rgValue
[i
].cbData
= 1 + nextLenBytes
+
3841 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3842 seq
->rgValue
[i
].pbData
= (BYTE
*)ptr
;
3845 seq
->rgValue
[i
].pbData
= nextPtr
;
3846 memcpy(nextPtr
, ptr
, 1 + nextLenBytes
+
3848 nextPtr
+= 1 + nextLenBytes
+ nextLen
;
3850 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
3851 ptr
+= 1 + nextLenBytes
+ nextLen
;
3861 SetLastError(CRYPT_E_ASN1_BADTAG
);
3867 SetLastError(STATUS_ACCESS_VIOLATION
);
3874 static BOOL
CRYPT_AsnDecodeDistPointName(const BYTE
*pbEncoded
,
3875 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
3880 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0))
3882 DWORD bytesNeeded
, dataLen
;
3884 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3886 struct AsnArrayDescriptor arrayDesc
= {
3887 ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, CRYPT_AsnDecodeAltNameEntry
,
3888 sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
3889 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
3890 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3896 ret
= CRYPT_AsnDecodeArray(&arrayDesc
,
3897 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
3898 0, NULL
, NULL
, &nameLen
, NULL
, NULL
);
3899 bytesNeeded
= sizeof(CRL_DIST_POINT_NAME
) + nameLen
;
3902 bytesNeeded
= sizeof(CRL_DIST_POINT_NAME
);
3904 *pcbDecoded
= 1 + lenBytes
+ dataLen
;
3906 *pcbStructInfo
= bytesNeeded
;
3907 else if (*pcbStructInfo
< bytesNeeded
)
3909 *pcbStructInfo
= bytesNeeded
;
3910 SetLastError(ERROR_MORE_DATA
);
3915 CRL_DIST_POINT_NAME
*name
= (CRL_DIST_POINT_NAME
*)pvStructInfo
;
3919 name
->dwDistPointNameChoice
= CRL_DIST_POINT_FULL_NAME
;
3920 ret
= CRYPT_AsnDecodeArray(&arrayDesc
,
3921 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
3922 0, NULL
, &name
->u
.FullName
, pcbStructInfo
, NULL
,
3923 name
->u
.FullName
.rgAltEntry
);
3926 name
->dwDistPointNameChoice
= CRL_DIST_POINT_NO_NAME
;
3932 SetLastError(CRYPT_E_ASN1_BADTAG
);
3938 static BOOL
CRYPT_AsnDecodeDistPoint(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3939 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
3941 struct AsnDecodeSequenceItem items
[] = {
3942 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_DIST_POINT
,
3943 DistPointName
), CRYPT_AsnDecodeDistPointName
,
3944 sizeof(CRL_DIST_POINT_NAME
), TRUE
, TRUE
, offsetof(CRL_DIST_POINT
,
3945 DistPointName
.u
.FullName
.rgAltEntry
), 0 },
3946 { ASN_CONTEXT
| 1, offsetof(CRL_DIST_POINT
, ReasonFlags
),
3947 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
3948 offsetof(CRL_DIST_POINT
, ReasonFlags
.pbData
), 0 },
3949 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2, offsetof(CRL_DIST_POINT
, CRLIssuer
),
3950 CRYPT_AsnDecodeAltNameInternal
, sizeof(CERT_ALT_NAME_INFO
), TRUE
, TRUE
,
3951 offsetof(CRL_DIST_POINT
, CRLIssuer
.rgAltEntry
), 0 },
3955 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
3956 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
3961 static BOOL WINAPI
CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType
,
3962 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3963 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3967 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3968 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3972 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3973 CRYPT_AsnDecodeDistPoint
, sizeof(CRL_DIST_POINT
), TRUE
,
3974 offsetof(CRL_DIST_POINT
, DistPointName
.u
.FullName
.rgAltEntry
) };
3976 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3977 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
, NULL
);
3981 SetLastError(STATUS_ACCESS_VIOLATION
);
3988 static BOOL WINAPI
CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3989 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3990 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3994 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3995 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3999 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
4000 CRYPT_AsnDecodeOidInternal
, sizeof(LPSTR
), TRUE
, 0 };
4002 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
4003 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
, NULL
);
4007 SetLastError(STATUS_ACCESS_VIOLATION
);
4014 static BOOL WINAPI
CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType
,
4015 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4016 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4020 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
4021 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4025 struct AsnDecodeSequenceItem items
[] = {
4026 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_ISSUING_DIST_POINT
,
4027 DistPointName
), CRYPT_AsnDecodeDistPointName
,
4028 sizeof(CRL_DIST_POINT_NAME
), TRUE
, TRUE
,
4029 offsetof(CRL_ISSUING_DIST_POINT
,
4030 DistPointName
.u
.FullName
.rgAltEntry
), 0 },
4031 { ASN_CONTEXT
| 1, offsetof(CRL_ISSUING_DIST_POINT
,
4032 fOnlyContainsUserCerts
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
,
4034 { ASN_CONTEXT
| 2, offsetof(CRL_ISSUING_DIST_POINT
,
4035 fOnlyContainsCACerts
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
,
4037 { ASN_CONTEXT
| 3, offsetof(CRL_ISSUING_DIST_POINT
,
4038 OnlySomeReasonFlags
), CRYPT_AsnDecodeBitsInternal
,
4039 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CRL_ISSUING_DIST_POINT
,
4040 OnlySomeReasonFlags
.pbData
), 0 },
4041 { ASN_CONTEXT
| 4, offsetof(CRL_ISSUING_DIST_POINT
,
4042 fIndirectCRL
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
, FALSE
, 0 },
4045 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
4046 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
4047 pcbStructInfo
, NULL
, NULL
);
4051 SetLastError(STATUS_ACCESS_VIOLATION
);
4058 static BOOL
CRYPT_AsnDecodeIssuerSerialNumber(const BYTE
*pbEncoded
,
4059 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
4063 struct AsnDecodeSequenceItem items
[] = {
4064 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER
, Issuer
), CRYPT_AsnDecodeDerBlob
,
4065 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_ISSUER_SERIAL_NUMBER
,
4067 { ASN_INTEGER
, offsetof(CERT_ISSUER_SERIAL_NUMBER
, SerialNumber
),
4068 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
,
4069 TRUE
, offsetof(CERT_ISSUER_SERIAL_NUMBER
, SerialNumber
.pbData
), 0 },
4071 CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
=
4072 (CERT_ISSUER_SERIAL_NUMBER
*)pvStructInfo
;
4074 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
4075 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
4077 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
4078 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
4079 pcbDecoded
, issuerSerial
? issuerSerial
->Issuer
.pbData
: NULL
);
4080 if (ret
&& issuerSerial
&& !issuerSerial
->SerialNumber
.cbData
)
4082 SetLastError(CRYPT_E_ASN1_CORRUPT
);
4085 TRACE("returning %d\n", ret
);
4089 static BOOL
CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE
*pbEncoded
,
4090 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
4093 CMSG_SIGNER_INFO
*info
= (CMSG_SIGNER_INFO
*)pvStructInfo
;
4094 struct AsnDecodeSequenceItem items
[] = {
4095 { ASN_INTEGER
, offsetof(CMSG_SIGNER_INFO
, dwVersion
),
4096 CRYPT_AsnDecodeIntInternal
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
4097 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, Issuer
),
4098 CRYPT_AsnDecodeIssuerSerialNumber
, sizeof(CERT_ISSUER_SERIAL_NUMBER
),
4099 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, Issuer
.pbData
), 0 },
4100 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, HashAlgorithm
),
4101 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
4102 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, HashAlgorithm
.pszObjId
), 0 },
4103 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0,
4104 offsetof(CMSG_SIGNER_INFO
, AuthAttrs
),
4105 CRYPT_AsnDecodePKCSAttributesInternal
, sizeof(CRYPT_ATTRIBUTES
),
4106 TRUE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, AuthAttrs
.rgAttr
), 0 },
4107 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, HashEncryptionAlgorithm
),
4108 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
4109 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
,
4110 HashEncryptionAlgorithm
.pszObjId
), 0 },
4111 { ASN_OCTETSTRING
, offsetof(CMSG_SIGNER_INFO
, EncryptedHash
),
4112 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_DER_BLOB
),
4113 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, EncryptedHash
.pbData
), 0 },
4114 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
4115 offsetof(CMSG_SIGNER_INFO
, UnauthAttrs
),
4116 CRYPT_AsnDecodePKCSAttributesInternal
, sizeof(CRYPT_ATTRIBUTES
),
4117 TRUE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, UnauthAttrs
.rgAttr
), 0 },
4121 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
4122 pvStructInfo
, *pcbStructInfo
);
4124 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
4125 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
,
4126 pcbDecoded
, info
? info
->Issuer
.pbData
: NULL
);
4130 static BOOL WINAPI
CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType
,
4131 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4132 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4136 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
4137 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
4141 ret
= CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded
, cbEncoded
,
4142 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pcbStructInfo
, NULL
);
4143 if (ret
&& pvStructInfo
)
4145 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
4146 pcbStructInfo
, *pcbStructInfo
);
4149 CMSG_SIGNER_INFO
*info
;
4151 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4152 pvStructInfo
= *(BYTE
**)pvStructInfo
;
4153 info
= (CMSG_SIGNER_INFO
*)pvStructInfo
;
4154 info
->Issuer
.pbData
= ((BYTE
*)info
+
4155 sizeof(CMSG_SIGNER_INFO
));
4156 ret
= CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded
,
4157 cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, pvStructInfo
,
4158 pcbStructInfo
, NULL
);
4164 SetLastError(STATUS_ACCESS_VIOLATION
);
4167 TRACE("returning %d\n", ret
);
4171 static BOOL
CRYPT_DecodeSignerArray(const BYTE
*pbEncoded
, DWORD cbEncoded
,
4172 DWORD dwFlags
, void *pvStructInfo
, DWORD
*pcbStructInfo
, DWORD
*pcbDecoded
)
4175 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
4176 CRYPT_AsnDecodePKCSSignerInfoInternal
, sizeof(CMSG_SIGNER_INFO
), TRUE
,
4177 offsetof(CMSG_SIGNER_INFO
, Issuer
.pbData
) };
4178 struct GenericArray
*array
= (struct GenericArray
*)pvStructInfo
;
4180 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded
, cbEncoded
, dwFlags
,
4181 pvStructInfo
, *pcbStructInfo
, pcbDecoded
);
4183 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
4184 NULL
, pvStructInfo
, pcbStructInfo
, pcbDecoded
,
4185 array
? array
->rgItems
: NULL
);
4189 BOOL
CRYPT_AsnDecodePKCSSignedInfo(const BYTE
*pbEncoded
, DWORD cbEncoded
,
4190 DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
4191 CRYPT_SIGNED_INFO
*signedInfo
, DWORD
*pcbSignedInfo
)
4194 struct AsnDecodeSequenceItem items
[] = {
4195 { ASN_INTEGER
, offsetof(CRYPT_SIGNED_INFO
, version
),
4196 CRYPT_AsnDecodeIntInternal
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
4197 /* Placeholder for the hash algorithms - redundant with those in the
4198 * signers, so just ignore them.
4200 { ASN_CONSTRUCTOR
| ASN_SETOF
, 0, NULL
, 0, TRUE
, FALSE
, 0, 0 },
4201 { ASN_SEQUENCE
, offsetof(CRYPT_SIGNED_INFO
, content
),
4202 CRYPT_AsnDecodePKCSContentInfoInternal
, sizeof(CRYPT_CONTENT_INFO
),
4203 FALSE
, TRUE
, offsetof(CRYPT_SIGNED_INFO
, content
.pszObjId
), 0 },
4204 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0,
4205 offsetof(CRYPT_SIGNED_INFO
, cCertEncoded
),
4206 CRYPT_DecodeDERArray
, sizeof(struct GenericArray
), TRUE
, TRUE
,
4207 offsetof(CRYPT_SIGNED_INFO
, rgCertEncoded
), 0 },
4208 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
4209 offsetof(CRYPT_SIGNED_INFO
, cCrlEncoded
), CRYPT_DecodeDERArray
,
4210 sizeof(struct GenericArray
), TRUE
, TRUE
,
4211 offsetof(CRYPT_SIGNED_INFO
, rgCrlEncoded
), 0 },
4212 { ASN_CONSTRUCTOR
| ASN_SETOF
, offsetof(CRYPT_SIGNED_INFO
, cSignerInfo
),
4213 CRYPT_DecodeSignerArray
, sizeof(struct GenericArray
), TRUE
, TRUE
,
4214 offsetof(CRYPT_SIGNED_INFO
, rgSignerInfo
), 0 },
4217 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
4218 pDecodePara
, signedInfo
, *pcbSignedInfo
);
4220 ret
= CRYPT_AsnDecodeSequence(items
, sizeof(items
) / sizeof(items
[0]),
4221 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, signedInfo
, pcbSignedInfo
,
4223 TRACE("returning %d\n", ret
);
4227 static CryptDecodeObjectExFunc
CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType
,
4228 LPCSTR lpszStructType
)
4230 CryptDecodeObjectExFunc decodeFunc
= NULL
;
4232 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
4233 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
4235 SetLastError(ERROR_FILE_NOT_FOUND
);
4238 if (!HIWORD(lpszStructType
))
4240 switch (LOWORD(lpszStructType
))
4242 case (WORD
)X509_CERT
:
4243 decodeFunc
= CRYPT_AsnDecodeCertSignedContent
;
4245 case (WORD
)X509_CERT_TO_BE_SIGNED
:
4246 decodeFunc
= CRYPT_AsnDecodeCert
;
4248 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
4249 decodeFunc
= CRYPT_AsnDecodeCRL
;
4251 case (WORD
)X509_EXTENSIONS
:
4252 decodeFunc
= CRYPT_AsnDecodeExtensions
;
4254 case (WORD
)X509_NAME_VALUE
:
4255 decodeFunc
= CRYPT_AsnDecodeNameValue
;
4257 case (WORD
)X509_NAME
:
4258 decodeFunc
= CRYPT_AsnDecodeName
;
4260 case (WORD
)X509_PUBLIC_KEY_INFO
:
4261 decodeFunc
= CRYPT_AsnDecodePubKeyInfo
;
4263 case (WORD
)X509_AUTHORITY_KEY_ID
:
4264 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId
;
4266 case (WORD
)X509_ALTERNATE_NAME
:
4267 decodeFunc
= CRYPT_AsnDecodeAltName
;
4269 case (WORD
)X509_BASIC_CONSTRAINTS
:
4270 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
4272 case (WORD
)X509_BASIC_CONSTRAINTS2
:
4273 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
4275 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
4276 decodeFunc
= CRYPT_AsnDecodeRsaPubKey
;
4278 case (WORD
)X509_UNICODE_NAME
:
4279 decodeFunc
= CRYPT_AsnDecodeUnicodeName
;
4281 case (WORD
)PKCS_ATTRIBUTE
:
4282 decodeFunc
= CRYPT_AsnDecodePKCSAttribute
;
4284 case (WORD
)X509_UNICODE_NAME_VALUE
:
4285 decodeFunc
= CRYPT_AsnDecodeUnicodeNameValue
;
4287 case (WORD
)X509_OCTET_STRING
:
4288 decodeFunc
= CRYPT_AsnDecodeOctets
;
4290 case (WORD
)X509_BITS
:
4291 case (WORD
)X509_KEY_USAGE
:
4292 decodeFunc
= CRYPT_AsnDecodeBits
;
4294 case (WORD
)X509_INTEGER
:
4295 decodeFunc
= CRYPT_AsnDecodeInt
;
4297 case (WORD
)X509_MULTI_BYTE_INTEGER
:
4298 decodeFunc
= CRYPT_AsnDecodeInteger
;
4300 case (WORD
)X509_MULTI_BYTE_UINT
:
4301 decodeFunc
= CRYPT_AsnDecodeUnsignedInteger
;
4303 case (WORD
)X509_ENUMERATED
:
4304 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
4306 case (WORD
)X509_CHOICE_OF_TIME
:
4307 decodeFunc
= CRYPT_AsnDecodeChoiceOfTime
;
4309 case (WORD
)X509_AUTHORITY_KEY_ID2
:
4310 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId2
;
4312 case (WORD
)PKCS_CONTENT_INFO
:
4313 decodeFunc
= CRYPT_AsnDecodePKCSContentInfo
;
4315 case (WORD
)X509_SEQUENCE_OF_ANY
:
4316 decodeFunc
= CRYPT_AsnDecodeSequenceOfAny
;
4318 case (WORD
)PKCS_UTC_TIME
:
4319 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
4321 case (WORD
)X509_CRL_DIST_POINTS
:
4322 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
4324 case (WORD
)X509_ENHANCED_KEY_USAGE
:
4325 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
4327 case (WORD
)PKCS_ATTRIBUTES
:
4328 decodeFunc
= CRYPT_AsnDecodePKCSAttributes
;
4330 case (WORD
)X509_ISSUING_DIST_POINT
:
4331 decodeFunc
= CRYPT_AsnDecodeIssuingDistPoint
;
4333 case (WORD
)PKCS7_SIGNER_INFO
:
4334 decodeFunc
= CRYPT_AsnDecodePKCSSignerInfo
;
4338 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4339 decodeFunc
= CRYPT_AsnDecodeExtensions
;
4340 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4341 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
4342 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4343 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId
;
4344 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4345 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId2
;
4346 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4347 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
4348 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4349 decodeFunc
= CRYPT_AsnDecodeBits
;
4350 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4351 decodeFunc
= CRYPT_AsnDecodeOctets
;
4352 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4353 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
4354 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4355 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
4356 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4357 decodeFunc
= CRYPT_AsnDecodeAltName
;
4358 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4359 decodeFunc
= CRYPT_AsnDecodeAltName
;
4360 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4361 decodeFunc
= CRYPT_AsnDecodeAltName
;
4362 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4363 decodeFunc
= CRYPT_AsnDecodeAltName
;
4364 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4365 decodeFunc
= CRYPT_AsnDecodeAltName
;
4366 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4367 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
4368 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4369 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
4370 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4371 decodeFunc
= CRYPT_AsnDecodeIssuingDistPoint
;
4375 static CryptDecodeObjectFunc
CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType
,
4376 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4378 static HCRYPTOIDFUNCSET set
= NULL
;
4379 CryptDecodeObjectFunc decodeFunc
= NULL
;
4382 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC
, 0);
4383 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4384 (void **)&decodeFunc
, hFunc
);
4388 static CryptDecodeObjectExFunc
CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType
,
4389 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4391 static HCRYPTOIDFUNCSET set
= NULL
;
4392 CryptDecodeObjectExFunc decodeFunc
= NULL
;
4395 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC
, 0);
4396 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4397 (void **)&decodeFunc
, hFunc
);
4401 BOOL WINAPI
CryptDecodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4402 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
,
4403 DWORD
*pcbStructInfo
)
4406 CryptDecodeObjectFunc pCryptDecodeObject
= NULL
;
4407 CryptDecodeObjectExFunc pCryptDecodeObjectEx
= NULL
;
4408 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4410 TRACE_(crypt
)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType
,
4411 debugstr_a(lpszStructType
), pbEncoded
, cbEncoded
, dwFlags
,
4412 pvStructInfo
, pcbStructInfo
);
4414 if (!pvStructInfo
&& !pcbStructInfo
)
4416 SetLastError(ERROR_INVALID_PARAMETER
);
4421 SetLastError(CRYPT_E_ASN1_EOD
);
4424 if (cbEncoded
> MAX_ENCODED_LEN
)
4426 SetLastError(CRYPT_E_ASN1_LARGE
);
4430 if (!(pCryptDecodeObjectEx
= CRYPT_GetBuiltinDecoder(dwCertEncodingType
,
4433 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4434 debugstr_a(lpszStructType
));
4435 pCryptDecodeObject
= CRYPT_LoadDecoderFunc(dwCertEncodingType
,
4436 lpszStructType
, &hFunc
);
4437 if (!pCryptDecodeObject
)
4438 pCryptDecodeObjectEx
= CRYPT_LoadDecoderExFunc(dwCertEncodingType
,
4439 lpszStructType
, &hFunc
);
4441 if (pCryptDecodeObject
)
4442 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
4443 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
4444 else if (pCryptDecodeObjectEx
)
4445 ret
= pCryptDecodeObjectEx(dwCertEncodingType
, lpszStructType
,
4446 pbEncoded
, cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
4447 pvStructInfo
, pcbStructInfo
);
4449 CryptFreeOIDFunctionAddress(hFunc
, 0);
4450 TRACE_(crypt
)("returning %d\n", ret
);
4454 BOOL WINAPI
CryptDecodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4455 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4456 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4459 CryptDecodeObjectExFunc decodeFunc
;
4460 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4462 TRACE_(crypt
)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4463 dwCertEncodingType
, debugstr_a(lpszStructType
), pbEncoded
,
4464 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
4466 if (!pvStructInfo
&& !pcbStructInfo
)
4468 SetLastError(ERROR_INVALID_PARAMETER
);
4473 SetLastError(CRYPT_E_ASN1_EOD
);
4476 if (cbEncoded
> MAX_ENCODED_LEN
)
4478 SetLastError(CRYPT_E_ASN1_LARGE
);
4482 SetLastError(NOERROR
);
4483 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
&& pvStructInfo
)
4484 *(BYTE
**)pvStructInfo
= NULL
;
4485 decodeFunc
= CRYPT_GetBuiltinDecoder(dwCertEncodingType
, lpszStructType
);
4488 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4489 debugstr_a(lpszStructType
));
4490 decodeFunc
= CRYPT_LoadDecoderExFunc(dwCertEncodingType
, lpszStructType
,
4494 ret
= decodeFunc(dwCertEncodingType
, lpszStructType
, pbEncoded
,
4495 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
4498 CryptDecodeObjectFunc pCryptDecodeObject
=
4499 CRYPT_LoadDecoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4501 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4502 * directly, as that could cause an infinite loop.
4504 if (pCryptDecodeObject
)
4506 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4508 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
4509 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pcbStructInfo
);
4510 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4511 pvStructInfo
, pcbStructInfo
, *pcbStructInfo
)))
4512 ret
= pCryptDecodeObject(dwCertEncodingType
,
4513 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
,
4514 *(BYTE
**)pvStructInfo
, pcbStructInfo
);
4517 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
4518 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
4522 CryptFreeOIDFunctionAddress(hFunc
, 0);
4523 TRACE_(crypt
)("returning %d\n", ret
);