2 * Copyright 2005 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface is
21 * undocumented, so I implement them here.
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
39 #define NONAMELESSUNION
46 #include "wine/debug.h"
47 #include "wine/exception.h"
48 #include "crypt32_private.h"
50 /* This is a bit arbitrary, but to set some limit: */
51 #define MAX_ENCODED_LEN 0x02000000
53 #define ASN_FLAGS_MASK 0xe0
54 #define ASN_TYPE_MASK 0x1f
56 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn
);
57 WINE_DECLARE_DEBUG_CHANNEL(crypt
);
65 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
66 DWORD
, DWORD
, void *, DWORD
*);
67 typedef BOOL (WINAPI
*CryptDecodeObjectExFunc
)(DWORD
, LPCSTR
, const BYTE
*,
68 DWORD
, DWORD
, PCRYPT_DECODE_PARA
, void *, DWORD
*);
70 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
71 * The dwCertEncodingType and lpszStructType are ignored by the built-in
72 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
73 * since it must call functions in external DLLs that follow these signatures.
75 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
76 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
77 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
78 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType
,
79 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
80 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
81 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
82 * time, doesn't do memory allocation, and doesn't do exception handling.
83 * (This isn't intended to be the externally-called one.)
85 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
86 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
87 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
88 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
89 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
90 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
91 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
92 /* Internal function */
93 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
94 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
95 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
96 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
97 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
98 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
99 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
100 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
101 * member has been initialized, doesn't do exception handling, and doesn't do
104 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
105 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
106 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
107 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
108 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
109 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
110 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
111 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
112 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
113 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
114 * member has been initialized, doesn't do exception handling, and doesn't do
115 * memory allocation. Also doesn't check tag, assumes the caller has checked
118 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
119 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
120 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
121 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
122 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
123 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
124 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
125 void *pvStructInfo
, DWORD
*pcbStructInfo
);
127 /* Gets the number of length bytes from the given (leading) length byte */
128 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
130 /* Helper function to get the encoded length of the data starting at pbEncoded,
131 * where pbEncoded[0] is the tag. If the data are too short to contain a
132 * length or if the length is too large for cbEncoded, sets an appropriate
133 * error code and returns FALSE.
135 static BOOL WINAPI
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
,
142 SetLastError(CRYPT_E_ASN1_CORRUPT
);
145 else if (pbEncoded
[1] <= 0x7f)
147 if (pbEncoded
[1] + 1 > cbEncoded
)
149 SetLastError(CRYPT_E_ASN1_EOD
);
158 else if (pbEncoded
[1] == 0x80)
160 FIXME("unimplemented for indefinite-length encoding\n");
161 SetLastError(CRYPT_E_ASN1_CORRUPT
);
166 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
168 if (lenLen
> sizeof(DWORD
) + 1)
170 SetLastError(CRYPT_E_ASN1_LARGE
);
173 else if (lenLen
+ 2 > cbEncoded
)
175 SetLastError(CRYPT_E_ASN1_CORRUPT
);
188 if (out
+ lenLen
+ 1 > cbEncoded
)
190 SetLastError(CRYPT_E_ASN1_EOD
);
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
);
235 * The expected tag of the item. If tag is 0, decodeFunc is called
236 * regardless of the tag value seen.
238 * A sequence is decoded into a struct. The offset member is the
239 * offset of this item within that struct.
241 * The decoder function to use. If this is NULL, then the member isn't
242 * decoded, but minSize space is reserved for it.
244 * The minimum amount of space occupied after decoding. You must set this.
246 * If true, and the tag doesn't match the expected tag for this item,
247 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
248 * filled with 0 for this member.
249 * hasPointer, pointerOffset:
250 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
251 * the offset within the struct of the data pointer (or to the
252 * first data pointer, if more than one exist).
254 * Used by CRYPT_AsnDecodeSequence, not for your use.
256 struct AsnDecodeSequenceItem
260 CryptDecodeObjectExFunc decodeFunc
;
268 /* Decodes the items in a sequence, where the items are described in items,
269 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
270 * pvStructInfo. nextData is a pointer to the memory location at which the
271 * first decoded item with a dynamic pointer should point.
272 * Upon decoding, *cbDecoded is the total number of bytes decoded.
274 static BOOL
CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType
,
275 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
276 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, BYTE
*nextData
,
280 DWORD i
, decoded
= 0;
281 const BYTE
*ptr
= pbEncoded
;
283 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items
, cItem
, pbEncoded
,
284 cbEncoded
, dwFlags
, pvStructInfo
, nextData
, cbDecoded
);
286 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
288 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
292 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
295 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
297 if (ptr
[0] == items
[i
].tag
|| !items
[i
].tag
)
299 if (nextData
&& pvStructInfo
&& items
[i
].hasPointer
)
301 TRACE("Setting next pointer to %p\n",
303 *(BYTE
**)((BYTE
*)pvStructInfo
+
304 items
[i
].pointerOffset
) = nextData
;
306 if (items
[i
].decodeFunc
)
309 TRACE("decoding item %d\n", i
);
311 TRACE("sizing item %d\n", i
);
312 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
313 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
314 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
315 pvStructInfo
? (BYTE
*)pvStructInfo
+ items
[i
].offset
316 : NULL
, &items
[i
].size
);
319 /* Account for alignment padding */
320 if (items
[i
].size
% sizeof(DWORD
))
321 items
[i
].size
+= sizeof(DWORD
) -
322 items
[i
].size
% sizeof(DWORD
);
323 TRACE("item %d size: %d\n", i
, items
[i
].size
);
324 if (nextData
&& items
[i
].hasPointer
&&
325 items
[i
].size
> items
[i
].minSize
)
326 nextData
+= items
[i
].size
- items
[i
].minSize
;
327 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
328 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
329 TRACE("item %d: decoded %d bytes\n", i
,
330 1 + nextItemLenBytes
+ nextItemLen
);
332 else if (items
[i
].optional
&&
333 GetLastError() == CRYPT_E_ASN1_BADTAG
)
335 TRACE("skipping optional item %d\n", i
);
336 items
[i
].size
= items
[i
].minSize
;
337 SetLastError(NOERROR
);
341 TRACE("item %d failed: %08x\n", i
,
346 TRACE("item %d: decoded %d bytes\n", i
,
347 1 + nextItemLenBytes
+ nextItemLen
);
348 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
349 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
350 items
[i
].size
= items
[i
].minSize
;
353 else if (items
[i
].optional
)
355 TRACE("skipping optional item %d\n", i
);
356 items
[i
].size
= items
[i
].minSize
;
360 TRACE("item %d: tag %02x doesn't match expected %02x\n",
361 i
, ptr
[0], items
[i
].tag
);
362 SetLastError(CRYPT_E_ASN1_BADTAG
);
367 else if (items
[i
].optional
)
369 TRACE("missing optional item %d, skipping\n", i
);
370 items
[i
].size
= items
[i
].minSize
;
374 TRACE("not enough bytes for item %d, failing\n", i
);
375 SetLastError(CRYPT_E_ASN1_CORRUPT
);
380 *cbDecoded
= decoded
;
381 TRACE("returning %d\n", ret
);
385 /* This decodes an arbitrary sequence into a contiguous block of memory
386 * (basically, a struct.) Each element being decoded is described by a struct
387 * AsnDecodeSequenceItem, see above.
388 * startingPointer is an optional pointer to the first place where dynamic
389 * data will be stored. If you know the starting offset, you may pass it
390 * here. Otherwise, pass NULL, and one will be inferred from the items.
391 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
393 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
394 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
395 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
396 void *pvStructInfo
, DWORD
*pcbStructInfo
, void *startingPointer
)
400 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items
, cItem
, pbEncoded
,
401 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
404 if (pbEncoded
[0] == ASN_SEQUENCE
)
408 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
410 DWORD lenBytes
= GET_LEN_BYTES(pbEncoded
[1]), cbDecoded
;
411 const BYTE
*ptr
= pbEncoded
+ 1 + lenBytes
;
413 cbEncoded
-= 1 + lenBytes
;
414 if (cbEncoded
< dataLen
)
416 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen
,
418 SetLastError(CRYPT_E_ASN1_CORRUPT
);
422 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
, ptr
,
423 cbEncoded
, dwFlags
, NULL
, NULL
, &cbDecoded
);
424 if (ret
&& cbDecoded
!= dataLen
)
426 TRACE("expected %d decoded, got %d, failing\n", dataLen
,
428 SetLastError(CRYPT_E_ASN1_CORRUPT
);
433 DWORD i
, bytesNeeded
= 0, structSize
= 0;
435 for (i
= 0; i
< cItem
; i
++)
437 bytesNeeded
+= items
[i
].size
;
438 structSize
+= items
[i
].minSize
;
441 *pcbStructInfo
= bytesNeeded
;
442 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
443 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
447 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
448 pvStructInfo
= *(BYTE
**)pvStructInfo
;
450 nextData
= (BYTE
*)startingPointer
;
452 nextData
= (BYTE
*)pvStructInfo
+ structSize
;
453 memset(pvStructInfo
, 0, structSize
);
454 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
,
455 ptr
, cbEncoded
, dwFlags
, pvStructInfo
, nextData
,
463 SetLastError(CRYPT_E_ASN1_BADTAG
);
466 TRACE("returning %d (%08x)\n", ret
, GetLastError());
471 * The expected tag of the entire encoded array (usually a variant
472 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
473 * regardless of the tag seen.
475 * used to decode each item in the array
477 * is the minimum size of each decoded item
479 * indicates whether each item has a dynamic pointer
481 * indicates the offset within itemSize at which the pointer exists
483 struct AsnArrayDescriptor
486 CryptDecodeObjectExFunc decodeFunc
;
492 struct AsnArrayItemSize
498 /* Decodes an array of like types into a struct GenericArray.
499 * The layout and decoding of the array are described by a struct
500 * AsnArrayDescriptor.
502 static BOOL
CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor
*arrayDesc
,
503 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
504 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
505 void *startingPointer
)
509 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc
, pbEncoded
,
510 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
513 if (!arrayDesc
->tag
|| pbEncoded
[0] == arrayDesc
->tag
)
517 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
519 DWORD bytesNeeded
, cItems
= 0;
520 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
521 /* There can be arbitrarily many items, but there is often only one.
523 struct AsnArrayItemSize itemSize
= { 0 }, *itemSizes
= &itemSize
;
525 bytesNeeded
= sizeof(struct GenericArray
);
530 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
531 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
533 DWORD itemLenBytes
, itemDataLen
, size
= 0;
535 itemLenBytes
= GET_LEN_BYTES(ptr
[1]);
536 /* Each item decoded may not tolerate extraneous bytes, so
537 * get the length of the next element and pass it directly.
539 ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
542 ret
= arrayDesc
->decodeFunc(X509_ASN_ENCODING
, 0, ptr
,
543 1 + itemLenBytes
+ itemDataLen
,
544 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
,
551 if (itemSizes
!= &itemSize
)
552 itemSizes
= CryptMemRealloc(itemSizes
,
553 cItems
* sizeof(struct AsnArrayItemSize
));
558 cItems
* sizeof(struct AsnArrayItemSize
));
560 memcpy(itemSizes
, &itemSize
, sizeof(itemSize
));
564 itemSizes
[cItems
- 1].encodedLen
= 1 + itemLenBytes
566 itemSizes
[cItems
- 1].size
= size
;
568 ret
= CRYPT_GetLen(ptr
,
569 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
571 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
581 *pcbStructInfo
= bytesNeeded
;
582 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
583 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
588 struct GenericArray
*array
;
590 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
591 pvStructInfo
= *(BYTE
**)pvStructInfo
;
592 array
= (struct GenericArray
*)pvStructInfo
;
593 array
->cItems
= cItems
;
595 array
->rgItems
= startingPointer
;
597 array
->rgItems
= (BYTE
*)array
+
598 sizeof(struct GenericArray
);
599 nextData
= (BYTE
*)array
->rgItems
+
600 array
->cItems
* arrayDesc
->itemSize
;
601 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
602 i
< cItems
&& ptr
- pbEncoded
- 1 - lenBytes
<
605 if (arrayDesc
->hasPointer
)
606 *(BYTE
**)(array
->rgItems
+ i
* arrayDesc
->itemSize
607 + arrayDesc
->pointerOffset
) = nextData
;
608 ret
= arrayDesc
->decodeFunc(X509_ASN_ENCODING
, 0, ptr
,
609 itemSizes
[i
].encodedLen
,
610 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
611 array
->rgItems
+ i
* arrayDesc
->itemSize
,
617 nextData
+= itemSizes
[i
].size
- arrayDesc
->itemSize
;
618 ret
= CRYPT_GetLen(ptr
,
619 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
621 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
626 if (itemSizes
!= &itemSize
)
627 CryptMemFree(itemSizes
);
632 SetLastError(CRYPT_E_ASN1_BADTAG
);
638 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
639 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
640 * to CRYPT_E_ASN1_CORRUPT.
641 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
644 static BOOL WINAPI
CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType
,
645 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
646 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
651 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
653 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
654 DWORD bytesNeeded
= sizeof(CRYPT_DER_BLOB
);
656 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
657 bytesNeeded
+= 1 + lenBytes
+ dataLen
;
660 *pcbStructInfo
= bytesNeeded
;
661 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
662 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
664 CRYPT_DER_BLOB
*blob
;
666 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
667 pvStructInfo
= *(BYTE
**)pvStructInfo
;
668 blob
= (CRYPT_DER_BLOB
*)pvStructInfo
;
669 blob
->cbData
= 1 + lenBytes
+ dataLen
;
672 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
673 blob
->pbData
= (BYTE
*)pbEncoded
;
676 assert(blob
->pbData
);
677 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
682 SetLastError(CRYPT_E_ASN1_CORRUPT
);
690 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
691 static BOOL WINAPI
CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType
,
692 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
693 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
697 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
698 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
700 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
703 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
, lpszStructType
,
704 pbEncoded
, cbEncoded
, dwFlags
& ~CRYPT_DECODE_NOCOPY_FLAG
, pDecodePara
,
705 pvStructInfo
, pcbStructInfo
);
706 if (ret
&& pvStructInfo
)
708 CRYPT_BIT_BLOB
*blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
715 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
717 temp
= blob
->pbData
[i
];
718 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
719 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
723 TRACE("returning %d (%08x)\n", ret
, GetLastError());
727 static BOOL WINAPI
CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType
,
728 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
729 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
733 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
734 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
738 struct AsnDecodeSequenceItem items
[] = {
739 { 0, offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
),
740 CRYPT_AsnDecodeDerBlob
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
741 offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
.pbData
), 0 },
742 { ASN_SEQUENCEOF
, offsetof(CERT_SIGNED_CONTENT_INFO
,
743 SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
744 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
,
745 offsetof(CERT_SIGNED_CONTENT_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
746 { ASN_BITSTRING
, offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
),
747 CRYPT_AsnDecodeBitsSwapBytes
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
748 offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
.pbData
), 0 },
751 if (dwFlags
& CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
752 items
[2].decodeFunc
= CRYPT_AsnDecodeBitsInternal
;
753 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
754 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
755 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
759 SetLastError(STATUS_ACCESS_VIOLATION
);
764 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
768 /* Internal function */
769 static BOOL WINAPI
CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType
,
770 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
771 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
776 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
778 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
780 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
781 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, pDecodePara
,
782 pvStructInfo
, pcbStructInfo
);
787 static BOOL WINAPI
CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType
,
788 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
789 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
793 struct AsnDecodeSequenceItem items
[] = {
794 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotBefore
),
795 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
796 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotAfter
),
797 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
800 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
801 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
802 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
806 /* Internal function */
807 static BOOL WINAPI
CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType
,
808 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
809 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
814 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
816 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
818 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
819 X509_EXTENSIONS
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
820 pDecodePara
, pvStructInfo
, pcbStructInfo
);
825 static BOOL WINAPI
CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType
,
826 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
827 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
830 struct AsnDecodeSequenceItem items
[] = {
831 { ASN_CONTEXT
| ASN_CONSTRUCTOR
, offsetof(CERT_INFO
, dwVersion
),
832 CRYPT_AsnDecodeCertVersion
, sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
833 { ASN_INTEGER
, offsetof(CERT_INFO
, SerialNumber
),
834 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
,
835 TRUE
, offsetof(CERT_INFO
, SerialNumber
.pbData
), 0 },
836 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, SignatureAlgorithm
),
837 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
838 FALSE
, TRUE
, offsetof(CERT_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
839 { 0, offsetof(CERT_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
840 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
842 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, NotBefore
),
843 CRYPT_AsnDecodeValidity
, sizeof(CERT_PRIVATE_KEY_VALIDITY
), FALSE
,
845 { 0, offsetof(CERT_INFO
, Subject
), CRYPT_AsnDecodeDerBlob
,
846 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
848 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, SubjectPublicKeyInfo
),
849 CRYPT_AsnDecodePubKeyInfoInternal
, sizeof(CERT_PUBLIC_KEY_INFO
),
850 FALSE
, TRUE
, offsetof(CERT_INFO
,
851 SubjectPublicKeyInfo
.Algorithm
.Parameters
.pbData
), 0 },
852 { ASN_BITSTRING
, offsetof(CERT_INFO
, IssuerUniqueId
),
853 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
854 offsetof(CERT_INFO
, IssuerUniqueId
.pbData
), 0 },
855 { ASN_BITSTRING
, offsetof(CERT_INFO
, SubjectUniqueId
),
856 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
857 offsetof(CERT_INFO
, SubjectUniqueId
.pbData
), 0 },
858 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 3, offsetof(CERT_INFO
, cExtension
),
859 CRYPT_AsnDecodeCertExtensions
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
860 offsetof(CERT_INFO
, rgExtension
), 0 },
863 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
864 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
866 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
867 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
868 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
869 if (ret
&& pvStructInfo
)
873 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
874 info
= *(CERT_INFO
**)pvStructInfo
;
876 info
= (CERT_INFO
*)pvStructInfo
;
877 if (!info
->SerialNumber
.cbData
|| !info
->Issuer
.cbData
||
878 !info
->Subject
.cbData
)
880 SetLastError(CRYPT_E_ASN1_CORRUPT
);
881 /* Don't need to deallocate, because it should have failed on the
882 * first pass (and no memory was allocated.)
888 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
892 static BOOL WINAPI
CRYPT_AsnDecodeCert(DWORD dwCertEncodingType
,
893 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
894 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
898 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
899 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
903 PCERT_SIGNED_CONTENT_INFO signedCert
= NULL
;
906 /* First try to decode it as a signed cert. */
907 ret
= CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType
, X509_CERT
,
908 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
909 (BYTE
*)&signedCert
, &size
);
913 ret
= CRYPT_AsnDecodeCertInfo(dwCertEncodingType
,
914 X509_CERT_TO_BE_SIGNED
, signedCert
->ToBeSigned
.pbData
,
915 signedCert
->ToBeSigned
.cbData
, dwFlags
, pDecodePara
, pvStructInfo
,
917 LocalFree(signedCert
);
919 /* Failing that, try it as an unsigned cert */
923 ret
= CRYPT_AsnDecodeCertInfo(dwCertEncodingType
,
924 X509_CERT_TO_BE_SIGNED
, pbEncoded
, cbEncoded
, dwFlags
,
925 pDecodePara
, pvStructInfo
, pcbStructInfo
);
930 SetLastError(STATUS_ACCESS_VIOLATION
);
935 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
939 static BOOL WINAPI
CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType
,
940 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
941 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
944 struct AsnDecodeSequenceItem items
[] = {
945 { ASN_INTEGER
, offsetof(CRL_ENTRY
, SerialNumber
),
946 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
,
947 offsetof(CRL_ENTRY
, SerialNumber
.pbData
), 0 },
948 { 0, offsetof(CRL_ENTRY
, RevocationDate
), CRYPT_AsnDecodeChoiceOfTime
,
949 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
950 { ASN_SEQUENCEOF
, offsetof(CRL_ENTRY
, cExtension
),
951 CRYPT_AsnDecodeExtensionsInternal
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
952 offsetof(CRL_ENTRY
, rgExtension
), 0 },
954 PCRL_ENTRY entry
= (PCRL_ENTRY
)pvStructInfo
;
956 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
, entry
,
959 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
960 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
961 NULL
, entry
, pcbStructInfo
, entry
? entry
->SerialNumber
.pbData
: NULL
);
965 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
966 * been set prior to calling.
968 static BOOL WINAPI
CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType
,
969 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
970 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
973 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
974 CRYPT_AsnDecodeCRLEntry
, sizeof(CRL_ENTRY
), TRUE
,
975 offsetof(CRL_ENTRY
, SerialNumber
.pbData
) };
976 struct GenericArray
*entries
= (struct GenericArray
*)pvStructInfo
;
978 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
979 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
981 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
982 pDecodePara
, pvStructInfo
, pcbStructInfo
,
983 entries
? entries
->rgItems
: NULL
);
984 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
988 static BOOL WINAPI
CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType
,
989 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
990 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
992 struct AsnDecodeSequenceItem items
[] = {
993 { ASN_INTEGER
, offsetof(CRL_INFO
, dwVersion
),
994 CRYPT_AsnDecodeInt
, sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
995 { ASN_SEQUENCEOF
, offsetof(CRL_INFO
, SignatureAlgorithm
),
996 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
997 FALSE
, TRUE
, offsetof(CRL_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
998 { 0, offsetof(CRL_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
999 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CRL_INFO
,
1001 { 0, offsetof(CRL_INFO
, ThisUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
1002 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
1003 { 0, offsetof(CRL_INFO
, NextUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
1004 sizeof(FILETIME
), TRUE
, FALSE
, 0 },
1005 { ASN_SEQUENCEOF
, offsetof(CRL_INFO
, cCRLEntry
),
1006 CRYPT_AsnDecodeCRLEntries
, sizeof(struct GenericArray
), TRUE
, TRUE
,
1007 offsetof(CRL_INFO
, rgCRLEntry
), 0 },
1008 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_INFO
, cExtension
),
1009 CRYPT_AsnDecodeCertExtensions
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
1010 offsetof(CRL_INFO
, rgExtension
), 0 },
1014 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1015 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1017 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1018 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1019 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
1021 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
1025 static BOOL WINAPI
CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType
,
1026 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1027 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1031 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1032 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1036 PCERT_SIGNED_CONTENT_INFO signedCrl
= NULL
;
1039 /* First try to decode it as a signed crl. */
1040 ret
= CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType
, X509_CERT
,
1041 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
1042 (BYTE
*)&signedCrl
, &size
);
1046 ret
= CRYPT_AsnDecodeCRLInfo(dwCertEncodingType
,
1047 X509_CERT_CRL_TO_BE_SIGNED
, signedCrl
->ToBeSigned
.pbData
,
1048 signedCrl
->ToBeSigned
.cbData
, dwFlags
, pDecodePara
,
1049 pvStructInfo
, pcbStructInfo
);
1050 LocalFree(signedCrl
);
1052 /* Failing that, try it as an unsigned crl */
1056 ret
= CRYPT_AsnDecodeCRLInfo(dwCertEncodingType
,
1057 X509_CERT_CRL_TO_BE_SIGNED
, pbEncoded
, cbEncoded
,
1058 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
1063 SetLastError(STATUS_ACCESS_VIOLATION
);
1068 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
1072 static BOOL WINAPI
CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType
,
1073 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1074 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1079 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1080 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1082 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1084 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1085 DWORD bytesNeeded
= sizeof(LPSTR
);
1089 /* The largest possible string for the first two components
1090 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1095 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
1096 pbEncoded
[1 + lenBytes
] / 40,
1097 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
1099 bytesNeeded
+= strlen(firstTwo
) + 1;
1100 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1101 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1103 /* large enough for ".4000000" */
1107 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1114 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
1117 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1124 snprintf(str
, sizeof(str
), ".%d", val
);
1125 bytesNeeded
+= strlen(str
);
1130 *pcbStructInfo
= bytesNeeded
;
1131 else if (*pcbStructInfo
< bytesNeeded
)
1133 *pcbStructInfo
= bytesNeeded
;
1134 SetLastError(ERROR_MORE_DATA
);
1142 LPSTR pszObjId
= *(LPSTR
*)pvStructInfo
;
1145 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
1146 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
1148 pszObjId
+= strlen(pszObjId
);
1149 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1150 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1154 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1163 sprintf(pszObjId
, ".%d", val
);
1164 pszObjId
+= strlen(pszObjId
);
1168 *(LPSTR
*)pvStructInfo
= NULL
;
1169 *pcbStructInfo
= bytesNeeded
;
1175 static BOOL WINAPI
CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType
,
1176 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1177 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1181 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1182 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1184 if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
1185 ret
= CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType
, lpszStructType
,
1186 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
1190 SetLastError(CRYPT_E_ASN1_BADTAG
);
1196 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1199 static BOOL WINAPI
CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType
,
1200 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1201 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1203 struct AsnDecodeSequenceItem items
[] = {
1204 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_EXTENSION
, pszObjId
),
1205 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1206 offsetof(CERT_EXTENSION
, pszObjId
), 0 },
1207 { ASN_BOOL
, offsetof(CERT_EXTENSION
, fCritical
), CRYPT_AsnDecodeBool
,
1208 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
1209 { ASN_OCTETSTRING
, offsetof(CERT_EXTENSION
, Value
),
1210 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_OBJID_BLOB
), FALSE
, TRUE
,
1211 offsetof(CERT_EXTENSION
, Value
.pbData
) },
1214 PCERT_EXTENSION ext
= (PCERT_EXTENSION
)pvStructInfo
;
1216 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
, ext
,
1220 TRACE("ext->pszObjId is %p\n", ext
->pszObjId
);
1221 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
1222 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
1223 ext
, pcbStructInfo
, ext
? ext
->pszObjId
: NULL
);
1225 TRACE("ext->pszObjId is %p (%s)\n", ext
->pszObjId
,
1226 debugstr_a(ext
->pszObjId
));
1227 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1231 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
1232 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1233 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1236 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1237 CRYPT_AsnDecodeExtension
, sizeof(CERT_EXTENSION
), TRUE
,
1238 offsetof(CERT_EXTENSION
, pszObjId
) };
1239 PCERT_EXTENSIONS exts
= (PCERT_EXTENSIONS
)pvStructInfo
;
1241 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1242 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1244 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1245 pDecodePara
, pvStructInfo
, pcbStructInfo
, exts
? exts
->rgExtension
: NULL
);
1249 static BOOL WINAPI
CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType
,
1250 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1251 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1257 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
1258 lpszStructType
, pbEncoded
, cbEncoded
,
1259 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
1260 if (ret
&& pvStructInfo
)
1262 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
1263 pcbStructInfo
, *pcbStructInfo
);
1266 CERT_EXTENSIONS
*exts
;
1268 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1269 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1270 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
1271 exts
->rgExtension
= (CERT_EXTENSION
*)((BYTE
*)exts
+
1272 sizeof(CERT_EXTENSIONS
));
1273 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
1274 lpszStructType
, pbEncoded
, cbEncoded
,
1275 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
1282 SetLastError(STATUS_ACCESS_VIOLATION
);
1289 /* Warning: this assumes the address of value->Value.pbData is already set, in
1290 * order to avoid overwriting memory. (In some cases, it may change it, if it
1291 * doesn't copy anything to memory.) Be sure to set it correctly!
1293 static BOOL WINAPI
CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType
,
1294 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1295 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1299 CERT_NAME_VALUE
*value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1301 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1303 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1304 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
), valueType
;
1306 switch (pbEncoded
[0])
1308 case ASN_OCTETSTRING
:
1309 valueType
= CERT_RDN_OCTET_STRING
;
1310 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1311 bytesNeeded
+= dataLen
;
1313 case ASN_NUMERICSTRING
:
1314 valueType
= CERT_RDN_NUMERIC_STRING
;
1315 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1316 bytesNeeded
+= dataLen
;
1318 case ASN_PRINTABLESTRING
:
1319 valueType
= CERT_RDN_PRINTABLE_STRING
;
1320 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1321 bytesNeeded
+= dataLen
;
1324 valueType
= CERT_RDN_IA5_STRING
;
1325 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1326 bytesNeeded
+= dataLen
;
1329 valueType
= CERT_RDN_T61_STRING
;
1330 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1331 bytesNeeded
+= dataLen
;
1333 case ASN_VIDEOTEXSTRING
:
1334 valueType
= CERT_RDN_VIDEOTEX_STRING
;
1335 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1336 bytesNeeded
+= dataLen
;
1338 case ASN_GRAPHICSTRING
:
1339 valueType
= CERT_RDN_GRAPHIC_STRING
;
1340 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1341 bytesNeeded
+= dataLen
;
1343 case ASN_VISIBLESTRING
:
1344 valueType
= CERT_RDN_VISIBLE_STRING
;
1345 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1346 bytesNeeded
+= dataLen
;
1348 case ASN_GENERALSTRING
:
1349 valueType
= CERT_RDN_GENERAL_STRING
;
1350 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1351 bytesNeeded
+= dataLen
;
1353 case ASN_UNIVERSALSTRING
:
1354 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1355 SetLastError(CRYPT_E_ASN1_BADTAG
);
1358 valueType
= CERT_RDN_BMP_STRING
;
1359 bytesNeeded
+= dataLen
;
1361 case ASN_UTF8STRING
:
1362 valueType
= CERT_RDN_UTF8_STRING
;
1363 bytesNeeded
+= MultiByteToWideChar(CP_UTF8
, 0,
1364 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
, NULL
, 0) * 2;
1367 SetLastError(CRYPT_E_ASN1_BADTAG
);
1372 *pcbStructInfo
= bytesNeeded
;
1373 else if (*pcbStructInfo
< bytesNeeded
)
1375 *pcbStructInfo
= bytesNeeded
;
1376 SetLastError(ERROR_MORE_DATA
);
1381 *pcbStructInfo
= bytesNeeded
;
1382 value
->dwValueType
= valueType
;
1387 assert(value
->Value
.pbData
);
1388 switch (pbEncoded
[0])
1390 case ASN_OCTETSTRING
:
1391 case ASN_NUMERICSTRING
:
1392 case ASN_PRINTABLESTRING
:
1395 case ASN_VIDEOTEXSTRING
:
1396 case ASN_GRAPHICSTRING
:
1397 case ASN_VISIBLESTRING
:
1398 case ASN_GENERALSTRING
:
1399 value
->Value
.cbData
= dataLen
;
1402 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1403 memcpy(value
->Value
.pbData
,
1404 pbEncoded
+ 1 + lenBytes
, dataLen
);
1406 value
->Value
.pbData
= (LPBYTE
)pbEncoded
+ 1 +
1412 LPWSTR str
= (LPWSTR
)value
->Value
.pbData
;
1414 value
->Value
.cbData
= dataLen
;
1415 for (i
= 0; i
< dataLen
/ 2; i
++)
1416 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
1417 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
1420 case ASN_UTF8STRING
:
1422 LPWSTR str
= (LPWSTR
)value
->Value
.pbData
;
1424 value
->Value
.cbData
= MultiByteToWideChar(CP_UTF8
, 0,
1425 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
,
1426 str
, bytesNeeded
- sizeof(CERT_NAME_VALUE
)) * 2;
1433 value
->Value
.cbData
= 0;
1434 value
->Value
.pbData
= NULL
;
1441 static BOOL WINAPI
CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType
,
1442 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1443 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1449 ret
= CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType
,
1450 lpszStructType
, pbEncoded
, cbEncoded
,
1451 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
1452 if (ret
&& pvStructInfo
)
1454 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
1455 pcbStructInfo
, *pcbStructInfo
);
1458 CERT_NAME_VALUE
*value
;
1460 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1461 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1462 value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1463 value
->Value
.pbData
= ((BYTE
*)value
+ sizeof(CERT_NAME_VALUE
));
1464 ret
= CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType
,
1465 lpszStructType
, pbEncoded
, cbEncoded
,
1466 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
1473 SetLastError(STATUS_ACCESS_VIOLATION
);
1480 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeNameValueInternal(
1481 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
1482 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
1483 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1487 CERT_NAME_VALUE
*value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1489 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1491 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1492 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
), valueType
;
1494 switch (pbEncoded
[0])
1496 case ASN_NUMERICSTRING
:
1497 valueType
= CERT_RDN_NUMERIC_STRING
;
1498 bytesNeeded
+= dataLen
* 2;
1500 case ASN_PRINTABLESTRING
:
1501 valueType
= CERT_RDN_PRINTABLE_STRING
;
1502 bytesNeeded
+= dataLen
* 2;
1505 valueType
= CERT_RDN_IA5_STRING
;
1506 bytesNeeded
+= dataLen
* 2;
1509 valueType
= CERT_RDN_T61_STRING
;
1510 bytesNeeded
+= dataLen
* 2;
1512 case ASN_VIDEOTEXSTRING
:
1513 valueType
= CERT_RDN_VIDEOTEX_STRING
;
1514 bytesNeeded
+= dataLen
* 2;
1516 case ASN_GRAPHICSTRING
:
1517 valueType
= CERT_RDN_GRAPHIC_STRING
;
1518 bytesNeeded
+= dataLen
* 2;
1520 case ASN_VISIBLESTRING
:
1521 valueType
= CERT_RDN_VISIBLE_STRING
;
1522 bytesNeeded
+= dataLen
* 2;
1524 case ASN_GENERALSTRING
:
1525 valueType
= CERT_RDN_GENERAL_STRING
;
1526 bytesNeeded
+= dataLen
* 2;
1528 case ASN_UNIVERSALSTRING
:
1529 valueType
= CERT_RDN_UNIVERSAL_STRING
;
1530 bytesNeeded
+= dataLen
/ 2;
1533 valueType
= CERT_RDN_BMP_STRING
;
1534 bytesNeeded
+= dataLen
;
1536 case ASN_UTF8STRING
:
1537 valueType
= CERT_RDN_UTF8_STRING
;
1538 bytesNeeded
+= MultiByteToWideChar(CP_UTF8
, 0,
1539 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
, NULL
, 0) * 2;
1542 SetLastError(CRYPT_E_ASN1_BADTAG
);
1547 *pcbStructInfo
= bytesNeeded
;
1548 else if (*pcbStructInfo
< bytesNeeded
)
1550 *pcbStructInfo
= bytesNeeded
;
1551 SetLastError(ERROR_MORE_DATA
);
1556 *pcbStructInfo
= bytesNeeded
;
1557 value
->dwValueType
= valueType
;
1561 LPWSTR str
= (LPWSTR
)value
->Value
.pbData
;
1563 assert(value
->Value
.pbData
);
1564 switch (pbEncoded
[0])
1566 case ASN_NUMERICSTRING
:
1567 case ASN_PRINTABLESTRING
:
1570 case ASN_VIDEOTEXSTRING
:
1571 case ASN_GRAPHICSTRING
:
1572 case ASN_VISIBLESTRING
:
1573 case ASN_GENERALSTRING
:
1574 value
->Value
.cbData
= dataLen
* 2;
1575 for (i
= 0; i
< dataLen
; i
++)
1576 str
[i
] = pbEncoded
[1 + lenBytes
+ i
];
1578 case ASN_UNIVERSALSTRING
:
1579 value
->Value
.cbData
= dataLen
/ 2;
1580 for (i
= 0; i
< dataLen
/ 4; i
++)
1581 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
+ 2] << 8)
1582 | pbEncoded
[1 + lenBytes
+ 2 * i
+ 3];
1585 value
->Value
.cbData
= dataLen
;
1586 for (i
= 0; i
< dataLen
/ 2; i
++)
1587 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
1588 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
1590 case ASN_UTF8STRING
:
1591 value
->Value
.cbData
= MultiByteToWideChar(CP_UTF8
, 0,
1592 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
,
1593 str
, bytesNeeded
- sizeof(CERT_NAME_VALUE
)) * 2;
1599 value
->Value
.cbData
= 0;
1600 value
->Value
.pbData
= NULL
;
1607 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType
,
1608 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1609 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1615 ret
= CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType
,
1616 lpszStructType
, pbEncoded
, cbEncoded
,
1617 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
1618 if (ret
&& pvStructInfo
)
1620 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
1621 pcbStructInfo
, *pcbStructInfo
);
1624 CERT_NAME_VALUE
*value
;
1626 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1627 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1628 value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1629 value
->Value
.pbData
= ((BYTE
*)value
+ sizeof(CERT_NAME_VALUE
));
1630 ret
= CRYPT_AsnDecodeUnicodeNameValueInternal(
1631 dwCertEncodingType
, lpszStructType
, pbEncoded
, cbEncoded
,
1632 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
1639 SetLastError(STATUS_ACCESS_VIOLATION
);
1646 static BOOL WINAPI
CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType
,
1647 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1648 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1651 struct AsnDecodeSequenceItem items
[] = {
1652 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_RDN_ATTR
, pszObjId
),
1653 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1654 offsetof(CERT_RDN_ATTR
, pszObjId
), 0 },
1655 { 0, offsetof(CERT_RDN_ATTR
, dwValueType
),
1656 CRYPT_AsnDecodeNameValueInternal
, sizeof(CERT_NAME_VALUE
),
1657 FALSE
, TRUE
, offsetof(CERT_RDN_ATTR
, Value
.pbData
), 0 },
1659 CERT_RDN_ATTR
*attr
= (CERT_RDN_ATTR
*)pvStructInfo
;
1661 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1662 pvStructInfo
, *pcbStructInfo
);
1665 TRACE("attr->pszObjId is %p\n", attr
->pszObjId
);
1666 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
1667 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
1668 attr
, pcbStructInfo
, attr
? attr
->pszObjId
: NULL
);
1671 TRACE("attr->pszObjId is %p (%s)\n", attr
->pszObjId
,
1672 debugstr_a(attr
->pszObjId
));
1673 TRACE("attr->dwValueType is %d\n", attr
->dwValueType
);
1675 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1679 static BOOL WINAPI
CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType
,
1680 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1681 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1684 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
1685 CRYPT_AsnDecodeRdnAttr
, sizeof(CERT_RDN_ATTR
), TRUE
,
1686 offsetof(CERT_RDN_ATTR
, pszObjId
) };
1687 PCERT_RDN rdn
= (PCERT_RDN
)pvStructInfo
;
1689 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1690 pDecodePara
, pvStructInfo
, pcbStructInfo
, rdn
? rdn
->rgRDNAttr
: NULL
);
1694 static BOOL WINAPI
CRYPT_AsnDecodeName(DWORD dwCertEncodingType
,
1695 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1696 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1702 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1703 CRYPT_AsnDecodeRdn
, sizeof(CERT_RDN
), TRUE
,
1704 offsetof(CERT_RDN
, rgRDNAttr
) };
1706 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1707 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
1711 SetLastError(STATUS_ACCESS_VIOLATION
);
1718 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType
,
1719 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1720 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1723 struct AsnDecodeSequenceItem items
[] = {
1724 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_RDN_ATTR
, pszObjId
),
1725 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1726 offsetof(CERT_RDN_ATTR
, pszObjId
), 0 },
1727 { 0, offsetof(CERT_RDN_ATTR
, dwValueType
),
1728 CRYPT_AsnDecodeUnicodeNameValueInternal
, sizeof(CERT_NAME_VALUE
),
1729 FALSE
, TRUE
, offsetof(CERT_RDN_ATTR
, Value
.pbData
), 0 },
1731 CERT_RDN_ATTR
*attr
= (CERT_RDN_ATTR
*)pvStructInfo
;
1733 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1734 pvStructInfo
, *pcbStructInfo
);
1737 TRACE("attr->pszObjId is %p\n", attr
->pszObjId
);
1738 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
1739 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
1740 attr
, pcbStructInfo
, attr
? attr
->pszObjId
: NULL
);
1743 TRACE("attr->pszObjId is %p (%s)\n", attr
->pszObjId
,
1744 debugstr_a(attr
->pszObjId
));
1745 TRACE("attr->dwValueType is %d\n", attr
->dwValueType
);
1747 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1751 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType
,
1752 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1753 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1756 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
1757 CRYPT_AsnDecodeUnicodeRdnAttr
, sizeof(CERT_RDN_ATTR
), TRUE
,
1758 offsetof(CERT_RDN_ATTR
, pszObjId
) };
1759 PCERT_RDN rdn
= (PCERT_RDN
)pvStructInfo
;
1761 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1762 pDecodePara
, pvStructInfo
, pcbStructInfo
, rdn
? rdn
->rgRDNAttr
: NULL
);
1766 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType
,
1767 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1768 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1774 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1775 CRYPT_AsnDecodeUnicodeRdn
, sizeof(CERT_RDN
), TRUE
,
1776 offsetof(CERT_RDN
, rgRDNAttr
) };
1778 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1779 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
1783 SetLastError(STATUS_ACCESS_VIOLATION
);
1790 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
1791 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1792 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1795 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
1797 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1798 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1800 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1801 bytesNeeded
+= cbEncoded
;
1803 *pcbStructInfo
= bytesNeeded
;
1804 else if (*pcbStructInfo
< bytesNeeded
)
1806 SetLastError(ERROR_MORE_DATA
);
1807 *pcbStructInfo
= bytesNeeded
;
1812 PCRYPT_OBJID_BLOB blob
= (PCRYPT_OBJID_BLOB
)pvStructInfo
;
1814 *pcbStructInfo
= bytesNeeded
;
1815 blob
->cbData
= cbEncoded
;
1816 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1817 blob
->pbData
= (LPBYTE
)pbEncoded
;
1820 assert(blob
->pbData
);
1821 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
1827 static BOOL WINAPI
CRYPT_DecodeDERArray(DWORD dwCertEncodingType
,
1828 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1829 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1832 struct AsnArrayDescriptor arrayDesc
= { 0, CRYPT_AsnDecodeCopyBytes
,
1833 sizeof(CRYPT_DER_BLOB
), TRUE
, offsetof(CRYPT_DER_BLOB
, pbData
) };
1834 struct GenericArray
*array
= (struct GenericArray
*)pvStructInfo
;
1836 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1837 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1839 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1840 pDecodePara
, pvStructInfo
, pcbStructInfo
, array
? array
->rgItems
: NULL
);
1844 static BOOL WINAPI
CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType
,
1845 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1846 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1852 struct AsnDecodeSequenceItem items
[] = {
1853 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ATTRIBUTE
, pszObjId
),
1854 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1855 offsetof(CRYPT_ATTRIBUTE
, pszObjId
), 0 },
1856 { ASN_CONSTRUCTOR
| ASN_SETOF
, offsetof(CRYPT_ATTRIBUTE
, cValue
),
1857 CRYPT_DecodeDERArray
, sizeof(struct GenericArray
), FALSE
, TRUE
,
1858 offsetof(CRYPT_ATTRIBUTE
, rgValue
), 0 },
1860 PCRYPT_ATTRIBUTE attr
= (PCRYPT_ATTRIBUTE
)pvStructInfo
;
1862 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1863 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1864 pDecodePara
, pvStructInfo
, pcbStructInfo
, attr
? attr
->pszObjId
:
1869 SetLastError(STATUS_ACCESS_VIOLATION
);
1872 TRACE("returning %d\n", ret
);
1876 static BOOL WINAPI
CRYPT_AsnDecodePKCSAttributesInternal(
1877 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
1878 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
1879 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1881 struct AsnArrayDescriptor arrayDesc
= { 0, CRYPT_AsnDecodePKCSAttribute
,
1882 sizeof(CRYPT_ATTRIBUTE
), TRUE
, offsetof(CRYPT_ATTRIBUTE
, pszObjId
) };
1883 PCRYPT_ATTRIBUTES attrs
= (PCRYPT_ATTRIBUTES
)pvStructInfo
;
1886 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1887 pDecodePara
, pvStructInfo
, pcbStructInfo
, attrs
? attrs
->rgAttr
:
1892 static BOOL WINAPI
CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType
,
1893 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1894 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1898 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1899 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1906 SetLastError(CRYPT_E_ASN1_EOD
);
1907 else if (pbEncoded
[0] != (ASN_CONSTRUCTOR
| ASN_SETOF
))
1908 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1909 else if ((ret
= CRYPT_AsnDecodePKCSAttributesInternal(
1910 dwCertEncodingType
, lpszStructType
, pbEncoded
, cbEncoded
,
1911 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
1914 *pcbStructInfo
= bytesNeeded
;
1915 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
1916 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
1918 PCRYPT_ATTRIBUTES attrs
;
1920 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1921 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1922 attrs
= (PCRYPT_ATTRIBUTES
)pvStructInfo
;
1923 attrs
->rgAttr
= (PCRYPT_ATTRIBUTE
)((BYTE
*)pvStructInfo
+
1924 sizeof(CRYPT_ATTRIBUTES
));
1925 ret
= CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType
,
1926 lpszStructType
, pbEncoded
, cbEncoded
,
1927 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
1934 SetLastError(STATUS_ACCESS_VIOLATION
);
1937 TRACE("returning %d\n", ret
);
1941 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
1942 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1943 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1945 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
1946 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
1948 struct AsnDecodeSequenceItem items
[] = {
1949 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
1950 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1951 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
1952 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
1953 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
1954 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
1957 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1958 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1960 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1961 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1962 pDecodePara
, pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
1963 if (ret
&& pvStructInfo
)
1965 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
1966 debugstr_a(algo
->pszObjId
));
1971 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType
,
1972 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1973 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1976 struct AsnDecodeSequenceItem items
[] = {
1977 { ASN_SEQUENCEOF
, offsetof(CERT_PUBLIC_KEY_INFO
, Algorithm
),
1978 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
1979 FALSE
, TRUE
, offsetof(CERT_PUBLIC_KEY_INFO
,
1980 Algorithm
.pszObjId
) },
1981 { ASN_BITSTRING
, offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
),
1982 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
1983 offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
.pbData
) },
1985 PCERT_PUBLIC_KEY_INFO info
= (PCERT_PUBLIC_KEY_INFO
)pvStructInfo
;
1987 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1988 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1989 pDecodePara
, pvStructInfo
, pcbStructInfo
, info
?
1990 info
->Algorithm
.Parameters
.pbData
: NULL
);
1994 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
1995 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1996 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2004 if ((ret
= CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType
,
2005 lpszStructType
, pbEncoded
, cbEncoded
,
2006 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
2009 *pcbStructInfo
= bytesNeeded
;
2010 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2011 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2013 PCERT_PUBLIC_KEY_INFO info
;
2015 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2016 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2017 info
= (PCERT_PUBLIC_KEY_INFO
)pvStructInfo
;
2018 info
->Algorithm
.Parameters
.pbData
= (BYTE
*)pvStructInfo
+
2019 sizeof(CERT_PUBLIC_KEY_INFO
);
2020 ret
= CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType
,
2021 lpszStructType
, pbEncoded
, cbEncoded
,
2022 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
2029 SetLastError(STATUS_ACCESS_VIOLATION
);
2036 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
2037 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2038 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2044 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2047 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
2049 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2052 if (pbEncoded
[1] > 1)
2054 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2059 *pcbStructInfo
= sizeof(BOOL
);
2062 else if (*pcbStructInfo
< sizeof(BOOL
))
2064 *pcbStructInfo
= sizeof(BOOL
);
2065 SetLastError(ERROR_MORE_DATA
);
2070 *(BOOL
*)pvStructInfo
= pbEncoded
[2] ? TRUE
: FALSE
;
2073 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2077 static BOOL WINAPI
CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType
,
2078 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2079 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2081 PCERT_ALT_NAME_ENTRY entry
= (PCERT_ALT_NAME_ENTRY
)pvStructInfo
;
2082 DWORD dataLen
, lenBytes
, bytesNeeded
= sizeof(CERT_ALT_NAME_ENTRY
);
2085 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2086 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2090 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2093 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2094 if (1 + lenBytes
> cbEncoded
)
2096 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2099 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2101 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
2103 case 1: /* rfc822Name */
2104 case 2: /* dNSName */
2105 case 6: /* uniformResourceIdentifier */
2106 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
2108 case 4: /* directoryName */
2109 case 7: /* iPAddress */
2110 bytesNeeded
+= dataLen
;
2112 case 8: /* registeredID */
2113 ret
= CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType
, NULL
,
2114 pbEncoded
, cbEncoded
, 0, NULL
, NULL
, &dataLen
);
2117 /* FIXME: ugly, shouldn't need to know internals of OID decode
2118 * function to use it.
2120 bytesNeeded
+= dataLen
- sizeof(LPSTR
);
2123 case 0: /* otherName */
2124 FIXME("%d: stub\n", pbEncoded
[0] & ASN_TYPE_MASK
);
2125 SetLastError(CRYPT_E_ASN1_BADTAG
);
2128 case 3: /* x400Address, unimplemented */
2129 case 5: /* ediPartyName, unimplemented */
2130 TRACE("type %d unimplemented\n", pbEncoded
[0] & ASN_TYPE_MASK
);
2131 SetLastError(CRYPT_E_ASN1_BADTAG
);
2135 TRACE("type %d bad\n", pbEncoded
[0] & ASN_TYPE_MASK
);
2136 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2142 *pcbStructInfo
= bytesNeeded
;
2143 else if (*pcbStructInfo
< bytesNeeded
)
2145 *pcbStructInfo
= bytesNeeded
;
2146 SetLastError(ERROR_MORE_DATA
);
2151 *pcbStructInfo
= bytesNeeded
;
2152 /* MS used values one greater than the asn1 ones.. sigh */
2153 entry
->dwAltNameChoice
= (pbEncoded
[0] & 0x7f) + 1;
2154 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
2156 case 1: /* rfc822Name */
2157 case 2: /* dNSName */
2158 case 6: /* uniformResourceIdentifier */
2162 for (i
= 0; i
< dataLen
; i
++)
2163 entry
->u
.pwszURL
[i
] =
2164 (WCHAR
)pbEncoded
[1 + lenBytes
+ i
];
2165 entry
->u
.pwszURL
[i
] = 0;
2166 TRACE("URL is %p (%s)\n", entry
->u
.pwszURL
,
2167 debugstr_w(entry
->u
.pwszURL
));
2170 case 4: /* directoryName */
2171 entry
->dwAltNameChoice
= CERT_ALT_NAME_DIRECTORY_NAME
;
2172 /* The data are memory-equivalent with the IPAddress case,
2175 case 7: /* iPAddress */
2176 /* The next data pointer is in the pwszURL spot, that is,
2177 * the first 4 bytes. Need to move it to the next spot.
2179 entry
->u
.IPAddress
.pbData
= (LPBYTE
)entry
->u
.pwszURL
;
2180 entry
->u
.IPAddress
.cbData
= dataLen
;
2181 memcpy(entry
->u
.IPAddress
.pbData
, pbEncoded
+ 1 + lenBytes
,
2184 case 8: /* registeredID */
2185 ret
= CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType
, NULL
,
2186 pbEncoded
, cbEncoded
, 0, NULL
, &entry
->u
.pszRegisteredID
,
2196 static BOOL WINAPI
CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType
,
2197 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2198 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2201 struct AsnArrayDescriptor arrayDesc
= { 0,
2202 CRYPT_AsnDecodeAltNameEntry
, sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
2203 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
2204 PCERT_ALT_NAME_INFO info
= (PCERT_ALT_NAME_INFO
)pvStructInfo
;
2206 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2207 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2210 TRACE("info->rgAltEntry is %p\n", info
->rgAltEntry
);
2211 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2212 pDecodePara
, pvStructInfo
, pcbStructInfo
, info
? info
->rgAltEntry
: NULL
);
2216 static BOOL WINAPI
CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType
,
2217 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2218 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2224 struct AsnDecodeSequenceItem items
[] = {
2225 { ASN_CONTEXT
| 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO
, KeyId
),
2226 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_DATA_BLOB
),
2227 TRUE
, TRUE
, offsetof(CERT_AUTHORITY_KEY_ID_INFO
, KeyId
.pbData
), 0 },
2228 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1,
2229 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertIssuer
),
2230 CRYPT_AsnDecodeOctetsInternal
, sizeof(CERT_NAME_BLOB
), TRUE
, TRUE
,
2231 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertIssuer
.pbData
), 0 },
2232 { ASN_CONTEXT
| 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO
,
2233 CertSerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2234 sizeof(CRYPT_INTEGER_BLOB
), TRUE
, TRUE
,
2235 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertSerialNumber
.pbData
), 0 },
2238 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2239 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2240 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2244 SetLastError(STATUS_ACCESS_VIOLATION
);
2251 static BOOL WINAPI
CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2252 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2253 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2259 struct AsnDecodeSequenceItem items
[] = {
2260 { ASN_CONTEXT
| 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, KeyId
),
2261 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_DATA_BLOB
),
2262 TRUE
, TRUE
, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, KeyId
.pbData
), 0 },
2263 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1,
2264 offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, AuthorityCertIssuer
),
2265 CRYPT_AsnDecodeAltNameInternal
, sizeof(CERT_ALT_NAME_INFO
), TRUE
,
2266 TRUE
, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2267 AuthorityCertIssuer
.rgAltEntry
), 0 },
2268 { ASN_CONTEXT
| 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2269 AuthorityCertSerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2270 sizeof(CRYPT_INTEGER_BLOB
), TRUE
, TRUE
,
2271 offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2272 AuthorityCertSerialNumber
.pbData
), 0 },
2275 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2276 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2277 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2281 SetLastError(STATUS_ACCESS_VIOLATION
);
2288 static BOOL WINAPI
CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType
,
2289 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2290 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2295 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2296 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2298 /* The caller has already checked the tag, no need to check it again.
2299 * Check the outer length is valid by calling CRYPT_GetLen:
2301 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2303 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2306 pbEncoded
+= 1 + lenBytes
;
2307 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2308 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &innerLen
)))
2310 ret
= CRYPT_AsnDecodeCopyBytes(dwCertEncodingType
, NULL
,
2311 pbEncoded
, dataLen
, dwFlags
, pDecodePara
, pvStructInfo
,
2318 static BOOL WINAPI
CRYPT_AsnDecodePKCSContentInfoInternal(
2319 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
2320 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2321 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2323 CRYPT_CONTENT_INFO
*info
= (CRYPT_CONTENT_INFO
*)pvStructInfo
;
2324 struct AsnDecodeSequenceItem items
[] = {
2325 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_CONTENT_INFO
, pszObjId
),
2326 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
2327 offsetof(CRYPT_CONTENT_INFO
, pszObjId
), 0 },
2328 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0,
2329 offsetof(CRYPT_CONTENT_INFO
, Content
), CRYPT_AsnDecodePKCSContent
,
2330 sizeof(CRYPT_DER_BLOB
), TRUE
, TRUE
,
2331 offsetof(CRYPT_CONTENT_INFO
, Content
.pbData
), 0 },
2335 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2336 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2338 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2339 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2340 pDecodePara
, pvStructInfo
, pcbStructInfo
, info
? info
->pszObjId
: NULL
);
2344 static BOOL WINAPI
CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType
,
2345 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2346 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2350 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2351 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2355 ret
= CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType
,
2356 lpszStructType
, pbEncoded
, cbEncoded
,
2357 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
2358 if (ret
&& pvStructInfo
)
2360 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
2361 pcbStructInfo
, *pcbStructInfo
);
2364 CRYPT_CONTENT_INFO
*info
;
2366 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2367 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2368 info
= (CRYPT_CONTENT_INFO
*)pvStructInfo
;
2369 info
->pszObjId
= (LPSTR
)((BYTE
*)info
+
2370 sizeof(CRYPT_CONTENT_INFO
));
2371 ret
= CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType
,
2372 lpszStructType
, pbEncoded
, cbEncoded
,
2373 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
2380 SetLastError(STATUS_ACCESS_VIOLATION
);
2386 BOOL
CRYPT_AsnDecodePKCSDigestedData(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2387 DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2388 CRYPT_DIGESTED_DATA
*digestedData
, DWORD
*pcbDigestedData
)
2391 struct AsnDecodeSequenceItem items
[] = {
2392 { ASN_INTEGER
, offsetof(CRYPT_DIGESTED_DATA
, version
), CRYPT_AsnDecodeInt
,
2393 sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
2394 { ASN_SEQUENCEOF
, offsetof(CRYPT_DIGESTED_DATA
, DigestAlgorithm
),
2395 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2396 FALSE
, TRUE
, offsetof(CRYPT_DIGESTED_DATA
, DigestAlgorithm
.pszObjId
),
2398 { ASN_SEQUENCEOF
, offsetof(CRYPT_DIGESTED_DATA
, ContentInfo
),
2399 CRYPT_AsnDecodePKCSContentInfoInternal
,
2400 sizeof(CRYPT_CONTENT_INFO
), FALSE
, TRUE
, offsetof(CRYPT_DIGESTED_DATA
,
2401 ContentInfo
.pszObjId
), 0 },
2402 { ASN_OCTETSTRING
, offsetof(CRYPT_DIGESTED_DATA
, hash
),
2403 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_HASH_BLOB
), FALSE
, TRUE
,
2404 offsetof(CRYPT_DIGESTED_DATA
, hash
.pbData
), 0 },
2407 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
2408 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2409 pDecodePara
, digestedData
, pcbDigestedData
, NULL
);
2413 static BOOL WINAPI
CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType
,
2414 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2415 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2419 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2420 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2424 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
2425 CRYPT_AsnDecodeAltNameEntry
, sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
2426 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
2428 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2429 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2433 SetLastError(STATUS_ACCESS_VIOLATION
);
2440 struct PATH_LEN_CONSTRAINT
2442 BOOL fPathLenConstraint
;
2443 DWORD dwPathLenConstraint
;
2446 static BOOL WINAPI
CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType
,
2447 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2448 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2452 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2453 pvStructInfo
, *pcbStructInfo
);
2457 if (pbEncoded
[0] == ASN_INTEGER
)
2459 DWORD bytesNeeded
= sizeof(struct PATH_LEN_CONSTRAINT
);
2462 *pcbStructInfo
= bytesNeeded
;
2463 else if (*pcbStructInfo
< bytesNeeded
)
2465 SetLastError(ERROR_MORE_DATA
);
2466 *pcbStructInfo
= bytesNeeded
;
2471 struct PATH_LEN_CONSTRAINT
*constraint
=
2472 (struct PATH_LEN_CONSTRAINT
*)pvStructInfo
;
2473 DWORD size
= sizeof(constraint
->dwPathLenConstraint
);
2475 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
2476 pbEncoded
, cbEncoded
, 0, NULL
,
2477 &constraint
->dwPathLenConstraint
, &size
);
2479 constraint
->fPathLenConstraint
= TRUE
;
2480 TRACE("got an int, dwPathLenConstraint is %d\n",
2481 constraint
->dwPathLenConstraint
);
2486 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2490 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2494 static BOOL WINAPI
CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType
,
2495 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2496 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2499 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
2500 CRYPT_AsnDecodeCopyBytes
, sizeof(CERT_NAME_BLOB
), TRUE
,
2501 offsetof(CERT_NAME_BLOB
, pbData
) };
2502 struct GenericArray
*entries
= (struct GenericArray
*)pvStructInfo
;
2504 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2505 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2507 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2508 pDecodePara
, pvStructInfo
, pcbStructInfo
,
2509 entries
? entries
->rgItems
: NULL
);
2510 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
2514 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType
,
2515 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2516 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2522 struct AsnDecodeSequenceItem items
[] = {
2523 { ASN_BITSTRING
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
),
2524 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
2525 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
.pbData
), 0 },
2526 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
2527 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
2528 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
2529 { ASN_SEQUENCEOF
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
2530 cSubtreesConstraint
), CRYPT_AsnDecodeSubtreeConstraints
,
2531 sizeof(struct GenericArray
), TRUE
, TRUE
,
2532 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, rgSubtreesConstraint
), 0 },
2535 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2536 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2537 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2541 SetLastError(STATUS_ACCESS_VIOLATION
);
2548 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType
,
2549 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2550 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2556 struct AsnDecodeSequenceItem items
[] = {
2557 { ASN_BOOL
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fCA
),
2558 CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
2559 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
,
2560 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
2561 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
2564 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2565 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2566 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2570 SetLastError(STATUS_ACCESS_VIOLATION
);
2577 #define RSA1_MAGIC 0x31415352
2579 struct DECODED_RSA_PUB_KEY
2582 CRYPT_INTEGER_BLOB modulus
;
2585 static BOOL WINAPI
CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType
,
2586 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2587 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2593 struct AsnDecodeSequenceItem items
[] = {
2594 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
),
2595 CRYPT_AsnDecodeUnsignedIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
),
2596 FALSE
, TRUE
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
.pbData
),
2598 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, pubexp
),
2599 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
2601 struct DECODED_RSA_PUB_KEY
*decodedKey
= NULL
;
2604 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2605 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
2606 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &decodedKey
, &size
, NULL
);
2609 DWORD bytesNeeded
= sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) +
2610 decodedKey
->modulus
.cbData
;
2614 *pcbStructInfo
= bytesNeeded
;
2617 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2618 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2621 RSAPUBKEY
*rsaPubKey
;
2623 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2624 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2625 hdr
= (BLOBHEADER
*)pvStructInfo
;
2626 hdr
->bType
= PUBLICKEYBLOB
;
2627 hdr
->bVersion
= CUR_BLOB_VERSION
;
2629 hdr
->aiKeyAlg
= CALG_RSA_KEYX
;
2630 rsaPubKey
= (RSAPUBKEY
*)((BYTE
*)pvStructInfo
+
2631 sizeof(BLOBHEADER
));
2632 rsaPubKey
->magic
= RSA1_MAGIC
;
2633 rsaPubKey
->pubexp
= decodedKey
->pubexp
;
2634 rsaPubKey
->bitlen
= decodedKey
->modulus
.cbData
* 8;
2635 memcpy((BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) +
2636 sizeof(RSAPUBKEY
), decodedKey
->modulus
.pbData
,
2637 decodedKey
->modulus
.cbData
);
2639 LocalFree(decodedKey
);
2644 SetLastError(STATUS_ACCESS_VIOLATION
);
2651 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
2652 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2653 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2656 DWORD bytesNeeded
, dataLen
;
2658 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2659 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2661 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2663 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2664 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
2666 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
2668 *pcbStructInfo
= bytesNeeded
;
2669 else if (*pcbStructInfo
< bytesNeeded
)
2671 SetLastError(ERROR_MORE_DATA
);
2672 *pcbStructInfo
= bytesNeeded
;
2677 CRYPT_DATA_BLOB
*blob
;
2678 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2680 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2681 blob
->cbData
= dataLen
;
2682 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2683 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
2686 assert(blob
->pbData
);
2688 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
2696 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
2697 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2698 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2702 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2703 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2711 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2714 else if (pbEncoded
[0] != ASN_OCTETSTRING
)
2716 SetLastError(CRYPT_E_ASN1_BADTAG
);
2719 else if ((ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
2720 lpszStructType
, pbEncoded
, cbEncoded
,
2721 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
2724 *pcbStructInfo
= bytesNeeded
;
2725 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2726 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2728 CRYPT_DATA_BLOB
*blob
;
2730 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2731 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2732 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2733 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_DATA_BLOB
);
2734 ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
2735 lpszStructType
, pbEncoded
, cbEncoded
,
2736 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
2743 SetLastError(STATUS_ACCESS_VIOLATION
);
2750 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
2751 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2752 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2756 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
2757 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2759 if (pbEncoded
[0] == ASN_BITSTRING
)
2761 DWORD bytesNeeded
, dataLen
;
2763 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2765 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2766 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
2768 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
2770 *pcbStructInfo
= bytesNeeded
;
2771 else if (*pcbStructInfo
< bytesNeeded
)
2773 *pcbStructInfo
= bytesNeeded
;
2774 SetLastError(ERROR_MORE_DATA
);
2779 CRYPT_BIT_BLOB
*blob
;
2781 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2782 blob
->cbData
= dataLen
- 1;
2783 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
2784 GET_LEN_BYTES(pbEncoded
[1]));
2785 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2787 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
2788 GET_LEN_BYTES(pbEncoded
[1]);
2792 assert(blob
->pbData
);
2795 BYTE mask
= 0xff << blob
->cUnusedBits
;
2797 memcpy(blob
->pbData
, pbEncoded
+ 2 +
2798 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
2799 blob
->pbData
[blob
->cbData
- 1] &= mask
;
2807 SetLastError(CRYPT_E_ASN1_BADTAG
);
2810 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2814 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
2815 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2816 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2820 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
2821 pDecodePara
, pvStructInfo
, pcbStructInfo
);
2827 if ((ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
2828 lpszStructType
, pbEncoded
, cbEncoded
,
2829 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
2832 *pcbStructInfo
= bytesNeeded
;
2833 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2834 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2836 CRYPT_BIT_BLOB
*blob
;
2838 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2839 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2840 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2841 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_BIT_BLOB
);
2842 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
2843 lpszStructType
, pbEncoded
, cbEncoded
,
2844 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
2851 SetLastError(STATUS_ACCESS_VIOLATION
);
2855 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2859 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
2860 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2861 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2867 *pcbStructInfo
= sizeof(int);
2872 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
2873 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
2874 DWORD size
= sizeof(buf
);
2876 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
2877 if (pbEncoded
[0] != ASN_INTEGER
)
2879 SetLastError(CRYPT_E_ASN1_BADTAG
);
2883 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
2884 X509_MULTI_BYTE_INTEGER
, pbEncoded
, cbEncoded
, 0, NULL
, &buf
,
2888 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2889 pvStructInfo
, pcbStructInfo
, sizeof(int))))
2893 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2894 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2895 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
2897 /* initialize to a negative value to sign-extend */
2902 for (i
= 0; i
< blob
->cbData
; i
++)
2905 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
2907 memcpy(pvStructInfo
, &val
, sizeof(int));
2910 else if (GetLastError() == ERROR_MORE_DATA
)
2911 SetLastError(CRYPT_E_ASN1_LARGE
);
2915 SetLastError(STATUS_ACCESS_VIOLATION
);
2922 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
2923 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2924 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2927 DWORD bytesNeeded
, dataLen
;
2929 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2931 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2933 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
2935 *pcbStructInfo
= bytesNeeded
;
2936 else if (*pcbStructInfo
< bytesNeeded
)
2938 *pcbStructInfo
= bytesNeeded
;
2939 SetLastError(ERROR_MORE_DATA
);
2944 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2946 blob
->cbData
= dataLen
;
2947 assert(blob
->pbData
);
2952 for (i
= 0; i
< blob
->cbData
; i
++)
2954 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
2963 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
2964 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2965 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2973 if (pbEncoded
[0] != ASN_INTEGER
)
2975 SetLastError(CRYPT_E_ASN1_BADTAG
);
2979 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
2980 lpszStructType
, pbEncoded
, cbEncoded
,
2981 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
);
2985 *pcbStructInfo
= bytesNeeded
;
2986 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2987 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2989 CRYPT_INTEGER_BLOB
*blob
;
2991 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2992 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2993 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2994 blob
->pbData
= (BYTE
*)pvStructInfo
+
2995 sizeof(CRYPT_INTEGER_BLOB
);
2996 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
2997 lpszStructType
, pbEncoded
, cbEncoded
,
2998 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3005 SetLastError(STATUS_ACCESS_VIOLATION
);
3012 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
3013 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
3014 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
3015 void *pvStructInfo
, DWORD
*pcbStructInfo
)
3019 if (pbEncoded
[0] == ASN_INTEGER
)
3021 DWORD bytesNeeded
, dataLen
;
3023 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3025 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3027 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
3029 *pcbStructInfo
= bytesNeeded
;
3030 else if (*pcbStructInfo
< bytesNeeded
)
3032 *pcbStructInfo
= bytesNeeded
;
3033 SetLastError(ERROR_MORE_DATA
);
3038 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3040 blob
->cbData
= dataLen
;
3041 assert(blob
->pbData
);
3042 /* remove leading zero byte if it exists */
3043 if (blob
->cbData
&& *(pbEncoded
+ 1 + lenBytes
) == 0)
3052 for (i
= 0; i
< blob
->cbData
; i
++)
3054 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
3063 SetLastError(CRYPT_E_ASN1_BADTAG
);
3069 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType
,
3070 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3071 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3079 if ((ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
3080 lpszStructType
, pbEncoded
, cbEncoded
,
3081 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
3084 *pcbStructInfo
= bytesNeeded
;
3085 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3086 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3088 CRYPT_INTEGER_BLOB
*blob
;
3090 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3091 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3092 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3093 blob
->pbData
= (BYTE
*)pvStructInfo
+
3094 sizeof(CRYPT_INTEGER_BLOB
);
3095 ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
3096 lpszStructType
, pbEncoded
, cbEncoded
,
3097 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3104 SetLastError(STATUS_ACCESS_VIOLATION
);
3111 static BOOL WINAPI
CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType
,
3112 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3113 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3119 *pcbStructInfo
= sizeof(int);
3124 if (pbEncoded
[0] == ASN_ENUMERATED
)
3126 unsigned int val
= 0, i
;
3130 SetLastError(CRYPT_E_ASN1_EOD
);
3133 else if (pbEncoded
[1] == 0)
3135 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3140 /* A little strange looking, but we have to accept a sign byte:
3141 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3142 * assuming a small length is okay here, it has to be in short
3145 if (pbEncoded
[1] > sizeof(unsigned int) + 1)
3147 SetLastError(CRYPT_E_ASN1_LARGE
);
3150 for (i
= 0; i
< pbEncoded
[1]; i
++)
3153 val
|= pbEncoded
[2 + i
];
3155 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3156 pvStructInfo
, pcbStructInfo
, sizeof(unsigned int))))
3158 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3159 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3160 memcpy(pvStructInfo
, &val
, sizeof(unsigned int));
3166 SetLastError(CRYPT_E_ASN1_BADTAG
);
3172 SetLastError(STATUS_ACCESS_VIOLATION
);
3179 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3182 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3187 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3189 if (!isdigit(*(pbEncoded))) \
3191 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3197 (word) += *(pbEncoded)++ - '0'; \
3202 static BOOL
CRYPT_AsnDecodeTimeZone(const BYTE
*pbEncoded
, DWORD len
,
3203 SYSTEMTIME
*sysTime
)
3210 if (len
>= 3 && (*pbEncoded
== '+' || *pbEncoded
== '-'))
3212 WORD hours
, minutes
= 0;
3213 BYTE sign
= *pbEncoded
++;
3216 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, hours
);
3217 if (ret
&& hours
>= 24)
3219 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3224 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, minutes
);
3225 if (ret
&& minutes
>= 60)
3227 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3235 sysTime
->wHour
+= hours
;
3236 sysTime
->wMinute
+= minutes
;
3240 if (hours
> sysTime
->wHour
)
3243 sysTime
->wHour
= 24 - (hours
- sysTime
->wHour
);
3246 sysTime
->wHour
-= hours
;
3247 if (minutes
> sysTime
->wMinute
)
3250 sysTime
->wMinute
= 60 - (minutes
- sysTime
->wMinute
);
3253 sysTime
->wMinute
-= minutes
;
3260 SetLastError(STATUS_ACCESS_VIOLATION
);
3267 #define MIN_ENCODED_TIME_LENGTH 10
3269 static BOOL WINAPI
CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType
,
3270 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3271 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3277 *pcbStructInfo
= sizeof(FILETIME
);
3283 if (pbEncoded
[0] == ASN_UTCTIME
)
3287 SetLastError(CRYPT_E_ASN1_EOD
);
3290 else if (pbEncoded
[1] > 0x7f)
3292 /* long-form date strings really can't be valid */
3293 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3298 SYSTEMTIME sysTime
= { 0 };
3299 BYTE len
= pbEncoded
[1];
3301 if (len
< MIN_ENCODED_TIME_LENGTH
)
3303 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3309 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wYear
);
3310 if (sysTime
.wYear
>= 50)
3311 sysTime
.wYear
+= 1900;
3313 sysTime
.wYear
+= 2000;
3314 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
3315 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
3316 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
3317 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMinute
);
3320 if (len
>= 2 && isdigit(*pbEncoded
) &&
3321 isdigit(*(pbEncoded
+ 1)))
3322 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3324 else if (isdigit(*pbEncoded
))
3325 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 1,
3328 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
3331 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3332 pDecodePara
, pvStructInfo
, pcbStructInfo
,
3335 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3336 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3337 ret
= SystemTimeToFileTime(&sysTime
,
3338 (FILETIME
*)pvStructInfo
);
3345 SetLastError(CRYPT_E_ASN1_BADTAG
);
3351 SetLastError(STATUS_ACCESS_VIOLATION
);
3358 static BOOL WINAPI
CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType
,
3359 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3360 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3366 *pcbStructInfo
= sizeof(FILETIME
);
3372 if (pbEncoded
[0] == ASN_GENERALTIME
)
3376 SetLastError(CRYPT_E_ASN1_EOD
);
3379 else if (pbEncoded
[1] > 0x7f)
3381 /* long-form date strings really can't be valid */
3382 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3387 BYTE len
= pbEncoded
[1];
3389 if (len
< MIN_ENCODED_TIME_LENGTH
)
3391 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3396 SYSTEMTIME sysTime
= { 0 };
3399 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 4, sysTime
.wYear
);
3400 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
3401 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
3402 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
3405 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3408 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3410 if (ret
&& len
> 0 && (*pbEncoded
== '.' ||
3417 /* workaround macro weirdness */
3418 digits
= min(len
, 3);
3419 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, digits
,
3420 sysTime
.wMilliseconds
);
3423 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
3426 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3427 pDecodePara
, pvStructInfo
, pcbStructInfo
,
3430 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3431 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3432 ret
= SystemTimeToFileTime(&sysTime
,
3433 (FILETIME
*)pvStructInfo
);
3440 SetLastError(CRYPT_E_ASN1_BADTAG
);
3446 SetLastError(STATUS_ACCESS_VIOLATION
);
3453 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
3454 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3455 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3461 if (pbEncoded
[0] == ASN_UTCTIME
)
3462 ret
= CRYPT_AsnDecodeUtcTime(dwCertEncodingType
, lpszStructType
,
3463 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
3465 else if (pbEncoded
[0] == ASN_GENERALTIME
)
3466 ret
= CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType
,
3467 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
,
3468 pvStructInfo
, pcbStructInfo
);
3471 SetLastError(CRYPT_E_ASN1_BADTAG
);
3477 SetLastError(STATUS_ACCESS_VIOLATION
);
3484 static BOOL WINAPI
CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType
,
3485 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3486 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3492 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3494 DWORD bytesNeeded
, dataLen
, remainingLen
, cValue
;
3496 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3501 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3502 bytesNeeded
= sizeof(CRYPT_SEQUENCE_OF_ANY
);
3504 ptr
= pbEncoded
+ 1 + lenBytes
;
3505 remainingLen
= dataLen
;
3506 while (ret
&& remainingLen
)
3510 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
3513 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
3515 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
3516 ptr
+= 1 + nextLenBytes
+ nextLen
;
3517 bytesNeeded
+= sizeof(CRYPT_DER_BLOB
);
3518 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3519 bytesNeeded
+= 1 + nextLenBytes
+ nextLen
;
3525 CRYPT_SEQUENCE_OF_ANY
*seq
;
3529 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3530 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3532 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3533 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3534 seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
3535 seq
->cValue
= cValue
;
3536 seq
->rgValue
= (CRYPT_DER_BLOB
*)((BYTE
*)seq
+
3538 nextPtr
= (BYTE
*)seq
->rgValue
+
3539 cValue
* sizeof(CRYPT_DER_BLOB
);
3540 ptr
= pbEncoded
+ 1 + lenBytes
;
3541 remainingLen
= dataLen
;
3543 while (ret
&& remainingLen
)
3547 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
3550 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
3552 seq
->rgValue
[i
].cbData
= 1 + nextLenBytes
+
3554 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3555 seq
->rgValue
[i
].pbData
= (BYTE
*)ptr
;
3558 seq
->rgValue
[i
].pbData
= nextPtr
;
3559 memcpy(nextPtr
, ptr
, 1 + nextLenBytes
+
3561 nextPtr
+= 1 + nextLenBytes
+ nextLen
;
3563 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
3564 ptr
+= 1 + nextLenBytes
+ nextLen
;
3574 SetLastError(CRYPT_E_ASN1_BADTAG
);
3580 SetLastError(STATUS_ACCESS_VIOLATION
);
3587 static BOOL WINAPI
CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType
,
3588 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3589 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3593 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0))
3595 DWORD bytesNeeded
, dataLen
;
3597 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3599 struct AsnArrayDescriptor arrayDesc
= {
3600 ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, CRYPT_AsnDecodeAltNameEntry
,
3601 sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
3602 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
3603 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3609 ret
= CRYPT_AsnDecodeArray(&arrayDesc
,
3610 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
3611 0, NULL
, NULL
, &nameLen
, NULL
);
3612 bytesNeeded
= sizeof(CRL_DIST_POINT_NAME
) + nameLen
;
3615 bytesNeeded
= sizeof(CRL_DIST_POINT_NAME
);
3617 *pcbStructInfo
= bytesNeeded
;
3618 else if (*pcbStructInfo
< bytesNeeded
)
3620 *pcbStructInfo
= bytesNeeded
;
3621 SetLastError(ERROR_MORE_DATA
);
3626 CRL_DIST_POINT_NAME
*name
= (CRL_DIST_POINT_NAME
*)pvStructInfo
;
3630 name
->dwDistPointNameChoice
= CRL_DIST_POINT_FULL_NAME
;
3631 ret
= CRYPT_AsnDecodeArray(&arrayDesc
,
3632 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
3633 0, NULL
, &name
->u
.FullName
, pcbStructInfo
,
3634 name
->u
.FullName
.rgAltEntry
);
3637 name
->dwDistPointNameChoice
= CRL_DIST_POINT_NO_NAME
;
3643 SetLastError(CRYPT_E_ASN1_BADTAG
);
3649 static BOOL WINAPI
CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType
,
3650 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3651 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3653 struct AsnDecodeSequenceItem items
[] = {
3654 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_DIST_POINT
,
3655 DistPointName
), CRYPT_AsnDecodeDistPointName
,
3656 sizeof(CRL_DIST_POINT_NAME
), TRUE
, TRUE
, offsetof(CRL_DIST_POINT
,
3657 DistPointName
.u
.FullName
.rgAltEntry
), 0 },
3658 { ASN_CONTEXT
| 1, offsetof(CRL_DIST_POINT
, ReasonFlags
),
3659 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
3660 offsetof(CRL_DIST_POINT
, ReasonFlags
.pbData
), 0 },
3661 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2, offsetof(CRL_DIST_POINT
, CRLIssuer
),
3662 CRYPT_AsnDecodeAltNameInternal
, sizeof(CERT_ALT_NAME_INFO
), TRUE
, TRUE
,
3663 offsetof(CRL_DIST_POINT
, CRLIssuer
.rgAltEntry
), 0 },
3667 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3668 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
3669 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3673 static BOOL WINAPI
CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType
,
3674 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3675 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3679 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3680 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3684 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3685 CRYPT_AsnDecodeDistPoint
, sizeof(CRL_DIST_POINT
), TRUE
,
3686 offsetof(CRL_DIST_POINT
, DistPointName
.u
.FullName
.rgAltEntry
) };
3688 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3689 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3693 SetLastError(STATUS_ACCESS_VIOLATION
);
3700 static BOOL WINAPI
CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3701 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3702 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3706 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3707 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3711 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3712 CRYPT_AsnDecodeOidInternal
, sizeof(LPSTR
), TRUE
, 0 };
3714 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3715 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3719 SetLastError(STATUS_ACCESS_VIOLATION
);
3726 static BOOL WINAPI
CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType
,
3727 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3728 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3732 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3733 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3737 struct AsnDecodeSequenceItem items
[] = {
3738 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_ISSUING_DIST_POINT
,
3739 DistPointName
), CRYPT_AsnDecodeDistPointName
,
3740 sizeof(CRL_DIST_POINT_NAME
), TRUE
, TRUE
,
3741 offsetof(CRL_ISSUING_DIST_POINT
,
3742 DistPointName
.u
.FullName
.rgAltEntry
), 0 },
3743 { ASN_CONTEXT
| 1, offsetof(CRL_ISSUING_DIST_POINT
,
3744 fOnlyContainsUserCerts
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
,
3746 { ASN_CONTEXT
| 2, offsetof(CRL_ISSUING_DIST_POINT
,
3747 fOnlyContainsCACerts
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
,
3749 { ASN_CONTEXT
| 3, offsetof(CRL_ISSUING_DIST_POINT
,
3750 OnlySomeReasonFlags
), CRYPT_AsnDecodeBitsInternal
,
3751 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CRL_ISSUING_DIST_POINT
,
3752 OnlySomeReasonFlags
.pbData
), 0 },
3753 { ASN_CONTEXT
| 4, offsetof(CRL_ISSUING_DIST_POINT
,
3754 fIndirectCRL
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
, FALSE
, 0 },
3757 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3758 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
3759 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3763 SetLastError(STATUS_ACCESS_VIOLATION
);
3770 static BOOL WINAPI
CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType
,
3771 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3772 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3775 struct AsnDecodeSequenceItem items
[] = {
3776 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER
, Issuer
), CRYPT_AsnDecodeDerBlob
,
3777 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_ISSUER_SERIAL_NUMBER
,
3779 { ASN_INTEGER
, offsetof(CERT_ISSUER_SERIAL_NUMBER
, SerialNumber
),
3780 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
,
3781 TRUE
, offsetof(CERT_ISSUER_SERIAL_NUMBER
, SerialNumber
.pbData
), 0 },
3783 CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
=
3784 (CERT_ISSUER_SERIAL_NUMBER
*)pvStructInfo
;
3786 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3787 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3789 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3790 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
3791 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
,
3792 issuerSerial
? issuerSerial
->Issuer
.pbData
: NULL
);
3793 if (ret
&& issuerSerial
&& !issuerSerial
->SerialNumber
.cbData
)
3795 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3798 TRACE("returning %d\n", ret
);
3802 static BOOL WINAPI
CRYPT_AsnDecodePKCSSignerInfoInternal(
3803 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
3804 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
3805 void *pvStructInfo
, DWORD
*pcbStructInfo
)
3807 CMSG_SIGNER_INFO
*info
= (CMSG_SIGNER_INFO
*)pvStructInfo
;
3808 struct AsnDecodeSequenceItem items
[] = {
3809 { ASN_INTEGER
, offsetof(CMSG_SIGNER_INFO
, dwVersion
),
3810 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
3811 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, Issuer
),
3812 CRYPT_AsnDecodeIssuerSerialNumber
, sizeof(CERT_ISSUER_SERIAL_NUMBER
),
3813 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, Issuer
.pbData
), 0 },
3814 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, HashAlgorithm
),
3815 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3816 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, HashAlgorithm
.pszObjId
), 0 },
3817 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0,
3818 offsetof(CMSG_SIGNER_INFO
, AuthAttrs
),
3819 CRYPT_AsnDecodePKCSAttributesInternal
, sizeof(CRYPT_ATTRIBUTES
),
3820 TRUE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, AuthAttrs
.rgAttr
), 0 },
3821 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, HashEncryptionAlgorithm
),
3822 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3823 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
,
3824 HashEncryptionAlgorithm
.pszObjId
), 0 },
3825 { ASN_OCTETSTRING
, offsetof(CMSG_SIGNER_INFO
, EncryptedHash
),
3826 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_DER_BLOB
),
3827 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, EncryptedHash
.pbData
), 0 },
3828 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
3829 offsetof(CMSG_SIGNER_INFO
, UnauthAttrs
),
3830 CRYPT_AsnDecodePKCSAttributesInternal
, sizeof(CRYPT_ATTRIBUTES
),
3831 TRUE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, UnauthAttrs
.rgAttr
), 0 },
3835 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3836 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3838 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3839 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
3840 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
,
3841 info
? info
->Issuer
.pbData
: NULL
);
3845 static BOOL WINAPI
CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType
,
3846 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3847 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3851 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3852 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3856 ret
= CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType
,
3857 lpszStructType
, pbEncoded
, cbEncoded
,
3858 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
3859 if (ret
&& pvStructInfo
)
3861 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
3862 pcbStructInfo
, *pcbStructInfo
);
3865 CMSG_SIGNER_INFO
*info
;
3867 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3868 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3869 info
= (CMSG_SIGNER_INFO
*)pvStructInfo
;
3870 info
->Issuer
.pbData
= ((BYTE
*)info
+
3871 sizeof(CMSG_SIGNER_INFO
));
3872 ret
= CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType
,
3873 lpszStructType
, pbEncoded
, cbEncoded
,
3874 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3881 SetLastError(STATUS_ACCESS_VIOLATION
);
3884 TRACE("returning %d\n", ret
);
3888 static BOOL WINAPI
CRYPT_DecodeSignerArray(DWORD dwCertEncodingType
,
3889 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3890 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3893 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
3894 CRYPT_AsnDecodePKCSSignerInfoInternal
, sizeof(CMSG_SIGNER_INFO
), TRUE
,
3895 offsetof(CMSG_SIGNER_INFO
, Issuer
.pbData
) };
3896 struct GenericArray
*array
= (struct GenericArray
*)pvStructInfo
;
3898 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3899 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3901 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3902 pDecodePara
, pvStructInfo
, pcbStructInfo
, array
? array
->rgItems
: NULL
);
3906 BOOL
CRYPT_AsnDecodePKCSSignedInfo(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3907 DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
3908 CRYPT_SIGNED_INFO
*signedInfo
, DWORD
*pcbSignedInfo
)
3911 struct AsnDecodeSequenceItem items
[] = {
3912 { ASN_INTEGER
, offsetof(CRYPT_SIGNED_INFO
, version
), CRYPT_AsnDecodeInt
,
3913 sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
3914 /* Placeholder for the hash algorithms - redundant with those in the
3915 * signers, so just ignore them.
3917 { ASN_CONSTRUCTOR
| ASN_SETOF
, 0, NULL
, 0, TRUE
, FALSE
, 0, 0 },
3918 { ASN_SEQUENCE
, offsetof(CRYPT_SIGNED_INFO
, content
),
3919 CRYPT_AsnDecodePKCSContentInfoInternal
, sizeof(CRYPT_CONTENT_INFO
),
3920 FALSE
, TRUE
, offsetof(CRYPT_SIGNED_INFO
, content
.pszObjId
), 0 },
3921 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0,
3922 offsetof(CRYPT_SIGNED_INFO
, cCertEncoded
),
3923 CRYPT_DecodeDERArray
, sizeof(struct GenericArray
), TRUE
, TRUE
,
3924 offsetof(CRYPT_SIGNED_INFO
, rgCertEncoded
), 0 },
3925 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
3926 offsetof(CRYPT_SIGNED_INFO
, cCrlEncoded
), CRYPT_DecodeDERArray
,
3927 sizeof(struct GenericArray
), TRUE
, TRUE
,
3928 offsetof(CRYPT_SIGNED_INFO
, rgCrlEncoded
), 0 },
3929 { ASN_CONSTRUCTOR
| ASN_SETOF
, offsetof(CRYPT_SIGNED_INFO
, cSignerInfo
),
3930 CRYPT_DecodeSignerArray
, sizeof(struct GenericArray
), TRUE
, TRUE
,
3931 offsetof(CRYPT_SIGNED_INFO
, rgSignerInfo
), 0 },
3934 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3935 pDecodePara
, signedInfo
, *pcbSignedInfo
);
3937 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3938 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3939 pDecodePara
, signedInfo
, pcbSignedInfo
, NULL
);
3940 TRACE("returning %d\n", ret
);
3944 static CryptDecodeObjectExFunc
CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType
,
3945 LPCSTR lpszStructType
)
3947 CryptDecodeObjectExFunc decodeFunc
= NULL
;
3949 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
3950 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
3952 SetLastError(ERROR_FILE_NOT_FOUND
);
3955 if (!HIWORD(lpszStructType
))
3957 switch (LOWORD(lpszStructType
))
3959 case (WORD
)X509_CERT
:
3960 decodeFunc
= CRYPT_AsnDecodeCertSignedContent
;
3962 case (WORD
)X509_CERT_TO_BE_SIGNED
:
3963 decodeFunc
= CRYPT_AsnDecodeCert
;
3965 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
3966 decodeFunc
= CRYPT_AsnDecodeCRL
;
3968 case (WORD
)X509_EXTENSIONS
:
3969 decodeFunc
= CRYPT_AsnDecodeExtensions
;
3971 case (WORD
)X509_NAME_VALUE
:
3972 decodeFunc
= CRYPT_AsnDecodeNameValue
;
3974 case (WORD
)X509_NAME
:
3975 decodeFunc
= CRYPT_AsnDecodeName
;
3977 case (WORD
)X509_PUBLIC_KEY_INFO
:
3978 decodeFunc
= CRYPT_AsnDecodePubKeyInfo
;
3980 case (WORD
)X509_AUTHORITY_KEY_ID
:
3981 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId
;
3983 case (WORD
)X509_ALTERNATE_NAME
:
3984 decodeFunc
= CRYPT_AsnDecodeAltName
;
3986 case (WORD
)X509_BASIC_CONSTRAINTS
:
3987 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
3989 case (WORD
)X509_BASIC_CONSTRAINTS2
:
3990 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
3992 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
3993 decodeFunc
= CRYPT_AsnDecodeRsaPubKey
;
3995 case (WORD
)X509_UNICODE_NAME
:
3996 decodeFunc
= CRYPT_AsnDecodeUnicodeName
;
3998 case (WORD
)PKCS_ATTRIBUTE
:
3999 decodeFunc
= CRYPT_AsnDecodePKCSAttribute
;
4001 case (WORD
)X509_UNICODE_NAME_VALUE
:
4002 decodeFunc
= CRYPT_AsnDecodeUnicodeNameValue
;
4004 case (WORD
)X509_OCTET_STRING
:
4005 decodeFunc
= CRYPT_AsnDecodeOctets
;
4007 case (WORD
)X509_BITS
:
4008 case (WORD
)X509_KEY_USAGE
:
4009 decodeFunc
= CRYPT_AsnDecodeBits
;
4011 case (WORD
)X509_INTEGER
:
4012 decodeFunc
= CRYPT_AsnDecodeInt
;
4014 case (WORD
)X509_MULTI_BYTE_INTEGER
:
4015 decodeFunc
= CRYPT_AsnDecodeInteger
;
4017 case (WORD
)X509_MULTI_BYTE_UINT
:
4018 decodeFunc
= CRYPT_AsnDecodeUnsignedInteger
;
4020 case (WORD
)X509_ENUMERATED
:
4021 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
4023 case (WORD
)X509_CHOICE_OF_TIME
:
4024 decodeFunc
= CRYPT_AsnDecodeChoiceOfTime
;
4026 case (WORD
)X509_AUTHORITY_KEY_ID2
:
4027 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId2
;
4029 case (WORD
)PKCS_CONTENT_INFO
:
4030 decodeFunc
= CRYPT_AsnDecodePKCSContentInfo
;
4032 case (WORD
)X509_SEQUENCE_OF_ANY
:
4033 decodeFunc
= CRYPT_AsnDecodeSequenceOfAny
;
4035 case (WORD
)PKCS_UTC_TIME
:
4036 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
4038 case (WORD
)X509_CRL_DIST_POINTS
:
4039 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
4041 case (WORD
)X509_ENHANCED_KEY_USAGE
:
4042 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
4044 case (WORD
)PKCS_ATTRIBUTES
:
4045 decodeFunc
= CRYPT_AsnDecodePKCSAttributes
;
4047 case (WORD
)X509_ISSUING_DIST_POINT
:
4048 decodeFunc
= CRYPT_AsnDecodeIssuingDistPoint
;
4050 case (WORD
)PKCS7_SIGNER_INFO
:
4051 decodeFunc
= CRYPT_AsnDecodePKCSSignerInfo
;
4055 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4056 decodeFunc
= CRYPT_AsnDecodeExtensions
;
4057 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4058 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
4059 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4060 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId
;
4061 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4062 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId2
;
4063 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4064 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
4065 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4066 decodeFunc
= CRYPT_AsnDecodeBits
;
4067 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4068 decodeFunc
= CRYPT_AsnDecodeOctets
;
4069 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4070 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
4071 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4072 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
4073 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4074 decodeFunc
= CRYPT_AsnDecodeAltName
;
4075 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4076 decodeFunc
= CRYPT_AsnDecodeAltName
;
4077 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4078 decodeFunc
= CRYPT_AsnDecodeAltName
;
4079 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4080 decodeFunc
= CRYPT_AsnDecodeAltName
;
4081 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4082 decodeFunc
= CRYPT_AsnDecodeAltName
;
4083 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4084 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
4085 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4086 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
4087 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4088 decodeFunc
= CRYPT_AsnDecodeIssuingDistPoint
;
4092 static CryptDecodeObjectFunc
CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType
,
4093 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4095 static HCRYPTOIDFUNCSET set
= NULL
;
4096 CryptDecodeObjectFunc decodeFunc
= NULL
;
4099 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC
, 0);
4100 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4101 (void **)&decodeFunc
, hFunc
);
4105 static CryptDecodeObjectExFunc
CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType
,
4106 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4108 static HCRYPTOIDFUNCSET set
= NULL
;
4109 CryptDecodeObjectExFunc decodeFunc
= NULL
;
4112 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC
, 0);
4113 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4114 (void **)&decodeFunc
, hFunc
);
4118 BOOL WINAPI
CryptDecodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4119 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
,
4120 DWORD
*pcbStructInfo
)
4123 CryptDecodeObjectFunc pCryptDecodeObject
= NULL
;
4124 CryptDecodeObjectExFunc pCryptDecodeObjectEx
= NULL
;
4125 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4127 TRACE_(crypt
)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType
,
4128 debugstr_a(lpszStructType
), pbEncoded
, cbEncoded
, dwFlags
,
4129 pvStructInfo
, pcbStructInfo
);
4131 if (!pvStructInfo
&& !pcbStructInfo
)
4133 SetLastError(ERROR_INVALID_PARAMETER
);
4138 SetLastError(CRYPT_E_ASN1_EOD
);
4141 if (cbEncoded
> MAX_ENCODED_LEN
)
4143 SetLastError(CRYPT_E_ASN1_LARGE
);
4147 if (!(pCryptDecodeObjectEx
= CRYPT_GetBuiltinDecoder(dwCertEncodingType
,
4150 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4151 debugstr_a(lpszStructType
));
4152 pCryptDecodeObject
= CRYPT_LoadDecoderFunc(dwCertEncodingType
,
4153 lpszStructType
, &hFunc
);
4154 if (!pCryptDecodeObject
)
4155 pCryptDecodeObjectEx
= CRYPT_LoadDecoderExFunc(dwCertEncodingType
,
4156 lpszStructType
, &hFunc
);
4158 if (pCryptDecodeObject
)
4159 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
4160 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
4161 else if (pCryptDecodeObjectEx
)
4162 ret
= pCryptDecodeObjectEx(dwCertEncodingType
, lpszStructType
,
4163 pbEncoded
, cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
4164 pvStructInfo
, pcbStructInfo
);
4166 CryptFreeOIDFunctionAddress(hFunc
, 0);
4167 TRACE_(crypt
)("returning %d\n", ret
);
4171 BOOL WINAPI
CryptDecodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4172 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4173 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4176 CryptDecodeObjectExFunc decodeFunc
;
4177 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4179 TRACE_(crypt
)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4180 dwCertEncodingType
, debugstr_a(lpszStructType
), pbEncoded
,
4181 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
4183 if (!pvStructInfo
&& !pcbStructInfo
)
4185 SetLastError(ERROR_INVALID_PARAMETER
);
4190 SetLastError(CRYPT_E_ASN1_EOD
);
4193 if (cbEncoded
> MAX_ENCODED_LEN
)
4195 SetLastError(CRYPT_E_ASN1_LARGE
);
4199 SetLastError(NOERROR
);
4200 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
&& pvStructInfo
)
4201 *(BYTE
**)pvStructInfo
= NULL
;
4202 decodeFunc
= CRYPT_GetBuiltinDecoder(dwCertEncodingType
, lpszStructType
);
4205 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4206 debugstr_a(lpszStructType
));
4207 decodeFunc
= CRYPT_LoadDecoderExFunc(dwCertEncodingType
, lpszStructType
,
4211 ret
= decodeFunc(dwCertEncodingType
, lpszStructType
, pbEncoded
,
4212 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
4215 CryptDecodeObjectFunc pCryptDecodeObject
=
4216 CRYPT_LoadDecoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4218 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4219 * directly, as that could cause an infinite loop.
4221 if (pCryptDecodeObject
)
4223 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4225 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
4226 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pcbStructInfo
);
4227 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4228 pvStructInfo
, pcbStructInfo
, *pcbStructInfo
)))
4229 ret
= pCryptDecodeObject(dwCertEncodingType
,
4230 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
,
4231 *(BYTE
**)pvStructInfo
, pcbStructInfo
);
4234 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
4235 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
4239 CryptFreeOIDFunctionAddress(hFunc
, 0);
4240 TRACE_(crypt
)("returning %d\n", ret
);