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 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2217 static BOOL WINAPI
CRYPT_AsnDecodeIntegerSwapBytes(DWORD dwCertEncodingType
,
2218 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2219 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2223 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
2224 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2226 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2229 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
, lpszStructType
,
2230 pbEncoded
, cbEncoded
, dwFlags
& ~CRYPT_DECODE_NOCOPY_FLAG
, pDecodePara
,
2231 pvStructInfo
, pcbStructInfo
);
2232 if (ret
&& pvStructInfo
)
2234 CRYPT_DATA_BLOB
*blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2241 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
2243 temp
= blob
->pbData
[i
];
2244 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
2245 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
2249 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2253 static BOOL WINAPI
CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType
,
2254 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2255 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2261 struct AsnDecodeSequenceItem items
[] = {
2262 { ASN_CONTEXT
| 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO
, KeyId
),
2263 CRYPT_AsnDecodeIntegerSwapBytes
, sizeof(CRYPT_DATA_BLOB
),
2264 TRUE
, TRUE
, offsetof(CERT_AUTHORITY_KEY_ID_INFO
, KeyId
.pbData
), 0 },
2265 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1,
2266 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertIssuer
),
2267 CRYPT_AsnDecodeOctetsInternal
, sizeof(CERT_NAME_BLOB
), TRUE
, TRUE
,
2268 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertIssuer
.pbData
), 0 },
2269 { ASN_CONTEXT
| 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO
,
2270 CertSerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2271 sizeof(CRYPT_INTEGER_BLOB
), TRUE
, TRUE
,
2272 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertSerialNumber
.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_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2289 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2290 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2296 struct AsnDecodeSequenceItem items
[] = {
2297 { ASN_CONTEXT
| 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, KeyId
),
2298 CRYPT_AsnDecodeIntegerSwapBytes
, sizeof(CRYPT_DATA_BLOB
),
2299 TRUE
, TRUE
, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, KeyId
.pbData
), 0 },
2300 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1,
2301 offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, AuthorityCertIssuer
),
2302 CRYPT_AsnDecodeAltNameInternal
, sizeof(CERT_ALT_NAME_INFO
), TRUE
,
2303 TRUE
, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2304 AuthorityCertIssuer
.rgAltEntry
), 0 },
2305 { ASN_CONTEXT
| 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2306 AuthorityCertSerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2307 sizeof(CRYPT_INTEGER_BLOB
), TRUE
, TRUE
,
2308 offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2309 AuthorityCertSerialNumber
.pbData
), 0 },
2312 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2313 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2314 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2318 SetLastError(STATUS_ACCESS_VIOLATION
);
2325 static BOOL WINAPI
CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType
,
2326 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2327 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2332 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2333 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2335 /* The caller has already checked the tag, no need to check it again.
2336 * Check the outer length is valid by calling CRYPT_GetLen:
2338 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2340 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2343 pbEncoded
+= 1 + lenBytes
;
2344 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2345 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &innerLen
)))
2347 ret
= CRYPT_AsnDecodeCopyBytes(dwCertEncodingType
, NULL
,
2348 pbEncoded
, dataLen
, dwFlags
, pDecodePara
, pvStructInfo
,
2355 static BOOL WINAPI
CRYPT_AsnDecodePKCSContentInfoInternal(
2356 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
2357 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2358 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2360 CRYPT_CONTENT_INFO
*info
= (CRYPT_CONTENT_INFO
*)pvStructInfo
;
2361 struct AsnDecodeSequenceItem items
[] = {
2362 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_CONTENT_INFO
, pszObjId
),
2363 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
2364 offsetof(CRYPT_CONTENT_INFO
, pszObjId
), 0 },
2365 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0,
2366 offsetof(CRYPT_CONTENT_INFO
, Content
), CRYPT_AsnDecodePKCSContent
,
2367 sizeof(CRYPT_DER_BLOB
), TRUE
, TRUE
,
2368 offsetof(CRYPT_CONTENT_INFO
, Content
.pbData
), 0 },
2372 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2373 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2375 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2376 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2377 pDecodePara
, pvStructInfo
, pcbStructInfo
, info
? info
->pszObjId
: NULL
);
2381 static BOOL WINAPI
CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType
,
2382 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2383 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2387 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2388 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2392 ret
= CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType
,
2393 lpszStructType
, pbEncoded
, cbEncoded
,
2394 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
2395 if (ret
&& pvStructInfo
)
2397 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
2398 pcbStructInfo
, *pcbStructInfo
);
2401 CRYPT_CONTENT_INFO
*info
;
2403 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2404 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2405 info
= (CRYPT_CONTENT_INFO
*)pvStructInfo
;
2406 info
->pszObjId
= (LPSTR
)((BYTE
*)info
+
2407 sizeof(CRYPT_CONTENT_INFO
));
2408 ret
= CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType
,
2409 lpszStructType
, pbEncoded
, cbEncoded
,
2410 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
2417 SetLastError(STATUS_ACCESS_VIOLATION
);
2423 BOOL
CRYPT_AsnDecodePKCSDigestedData(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2424 DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2425 CRYPT_DIGESTED_DATA
*digestedData
, DWORD
*pcbDigestedData
)
2428 struct AsnDecodeSequenceItem items
[] = {
2429 { ASN_INTEGER
, offsetof(CRYPT_DIGESTED_DATA
, version
), CRYPT_AsnDecodeInt
,
2430 sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
2431 { ASN_SEQUENCEOF
, offsetof(CRYPT_DIGESTED_DATA
, DigestAlgorithm
),
2432 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2433 FALSE
, TRUE
, offsetof(CRYPT_DIGESTED_DATA
, DigestAlgorithm
.pszObjId
),
2435 { ASN_SEQUENCEOF
, offsetof(CRYPT_DIGESTED_DATA
, ContentInfo
),
2436 CRYPT_AsnDecodePKCSContentInfoInternal
,
2437 sizeof(CRYPT_CONTENT_INFO
), FALSE
, TRUE
, offsetof(CRYPT_DIGESTED_DATA
,
2438 ContentInfo
.pszObjId
), 0 },
2439 { ASN_OCTETSTRING
, offsetof(CRYPT_DIGESTED_DATA
, hash
),
2440 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_HASH_BLOB
), FALSE
, TRUE
,
2441 offsetof(CRYPT_DIGESTED_DATA
, hash
.pbData
), 0 },
2444 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
2445 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2446 pDecodePara
, digestedData
, pcbDigestedData
, NULL
);
2450 static BOOL WINAPI
CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType
,
2451 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2452 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2456 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2457 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2461 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
2462 CRYPT_AsnDecodeAltNameEntry
, sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
2463 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
2465 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2466 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2470 SetLastError(STATUS_ACCESS_VIOLATION
);
2477 struct PATH_LEN_CONSTRAINT
2479 BOOL fPathLenConstraint
;
2480 DWORD dwPathLenConstraint
;
2483 static BOOL WINAPI
CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType
,
2484 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2485 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2489 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2490 pvStructInfo
, *pcbStructInfo
);
2494 if (pbEncoded
[0] == ASN_INTEGER
)
2496 DWORD bytesNeeded
= sizeof(struct PATH_LEN_CONSTRAINT
);
2499 *pcbStructInfo
= bytesNeeded
;
2500 else if (*pcbStructInfo
< bytesNeeded
)
2502 SetLastError(ERROR_MORE_DATA
);
2503 *pcbStructInfo
= bytesNeeded
;
2508 struct PATH_LEN_CONSTRAINT
*constraint
=
2509 (struct PATH_LEN_CONSTRAINT
*)pvStructInfo
;
2510 DWORD size
= sizeof(constraint
->dwPathLenConstraint
);
2512 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
2513 pbEncoded
, cbEncoded
, 0, NULL
,
2514 &constraint
->dwPathLenConstraint
, &size
);
2516 constraint
->fPathLenConstraint
= TRUE
;
2517 TRACE("got an int, dwPathLenConstraint is %d\n",
2518 constraint
->dwPathLenConstraint
);
2523 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2527 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2531 static BOOL WINAPI
CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType
,
2532 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2533 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2536 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
2537 CRYPT_AsnDecodeCopyBytes
, sizeof(CERT_NAME_BLOB
), TRUE
,
2538 offsetof(CERT_NAME_BLOB
, pbData
) };
2539 struct GenericArray
*entries
= (struct GenericArray
*)pvStructInfo
;
2541 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2542 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2544 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2545 pDecodePara
, pvStructInfo
, pcbStructInfo
,
2546 entries
? entries
->rgItems
: NULL
);
2547 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
2551 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType
,
2552 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2553 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2559 struct AsnDecodeSequenceItem items
[] = {
2560 { ASN_BITSTRING
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
),
2561 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
2562 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
.pbData
), 0 },
2563 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
2564 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
2565 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
2566 { ASN_SEQUENCEOF
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
2567 cSubtreesConstraint
), CRYPT_AsnDecodeSubtreeConstraints
,
2568 sizeof(struct GenericArray
), TRUE
, TRUE
,
2569 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, rgSubtreesConstraint
), 0 },
2572 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2573 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2574 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2578 SetLastError(STATUS_ACCESS_VIOLATION
);
2585 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints2(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_BOOL
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fCA
),
2595 CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
2596 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
,
2597 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
2598 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
2601 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2602 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2603 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2607 SetLastError(STATUS_ACCESS_VIOLATION
);
2614 #define RSA1_MAGIC 0x31415352
2616 struct DECODED_RSA_PUB_KEY
2619 CRYPT_INTEGER_BLOB modulus
;
2622 static BOOL WINAPI
CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType
,
2623 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2624 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2630 struct AsnDecodeSequenceItem items
[] = {
2631 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
),
2632 CRYPT_AsnDecodeUnsignedIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
),
2633 FALSE
, TRUE
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
.pbData
),
2635 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, pubexp
),
2636 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
2638 struct DECODED_RSA_PUB_KEY
*decodedKey
= NULL
;
2641 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2642 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
2643 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &decodedKey
, &size
, NULL
);
2646 DWORD bytesNeeded
= sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) +
2647 decodedKey
->modulus
.cbData
;
2651 *pcbStructInfo
= bytesNeeded
;
2654 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2655 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2658 RSAPUBKEY
*rsaPubKey
;
2660 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2661 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2662 hdr
= (BLOBHEADER
*)pvStructInfo
;
2663 hdr
->bType
= PUBLICKEYBLOB
;
2664 hdr
->bVersion
= CUR_BLOB_VERSION
;
2666 hdr
->aiKeyAlg
= CALG_RSA_KEYX
;
2667 rsaPubKey
= (RSAPUBKEY
*)((BYTE
*)pvStructInfo
+
2668 sizeof(BLOBHEADER
));
2669 rsaPubKey
->magic
= RSA1_MAGIC
;
2670 rsaPubKey
->pubexp
= decodedKey
->pubexp
;
2671 rsaPubKey
->bitlen
= decodedKey
->modulus
.cbData
* 8;
2672 memcpy((BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) +
2673 sizeof(RSAPUBKEY
), decodedKey
->modulus
.pbData
,
2674 decodedKey
->modulus
.cbData
);
2676 LocalFree(decodedKey
);
2681 SetLastError(STATUS_ACCESS_VIOLATION
);
2688 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
2689 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2690 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2693 DWORD bytesNeeded
, dataLen
;
2695 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2696 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2698 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2700 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2701 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
2703 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
2705 *pcbStructInfo
= bytesNeeded
;
2706 else if (*pcbStructInfo
< bytesNeeded
)
2708 SetLastError(ERROR_MORE_DATA
);
2709 *pcbStructInfo
= bytesNeeded
;
2714 CRYPT_DATA_BLOB
*blob
;
2715 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2717 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2718 blob
->cbData
= dataLen
;
2719 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2720 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
2723 assert(blob
->pbData
);
2725 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
2733 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
2734 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2735 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2739 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2740 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2748 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2751 else if (pbEncoded
[0] != ASN_OCTETSTRING
)
2753 SetLastError(CRYPT_E_ASN1_BADTAG
);
2756 else if ((ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
2757 lpszStructType
, pbEncoded
, cbEncoded
,
2758 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
2761 *pcbStructInfo
= bytesNeeded
;
2762 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2763 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2765 CRYPT_DATA_BLOB
*blob
;
2767 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2768 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2769 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2770 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_DATA_BLOB
);
2771 ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
2772 lpszStructType
, pbEncoded
, cbEncoded
,
2773 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
2780 SetLastError(STATUS_ACCESS_VIOLATION
);
2787 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
2788 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2789 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2793 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
2794 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2796 if (pbEncoded
[0] == ASN_BITSTRING
)
2798 DWORD bytesNeeded
, dataLen
;
2800 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2802 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2803 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
2805 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
2807 *pcbStructInfo
= bytesNeeded
;
2808 else if (*pcbStructInfo
< bytesNeeded
)
2810 *pcbStructInfo
= bytesNeeded
;
2811 SetLastError(ERROR_MORE_DATA
);
2816 CRYPT_BIT_BLOB
*blob
;
2818 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2819 blob
->cbData
= dataLen
- 1;
2820 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
2821 GET_LEN_BYTES(pbEncoded
[1]));
2822 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2824 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
2825 GET_LEN_BYTES(pbEncoded
[1]);
2829 assert(blob
->pbData
);
2832 BYTE mask
= 0xff << blob
->cUnusedBits
;
2834 memcpy(blob
->pbData
, pbEncoded
+ 2 +
2835 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
2836 blob
->pbData
[blob
->cbData
- 1] &= mask
;
2844 SetLastError(CRYPT_E_ASN1_BADTAG
);
2847 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2851 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
2852 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2853 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2857 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
2858 pDecodePara
, pvStructInfo
, pcbStructInfo
);
2864 if ((ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
2865 lpszStructType
, pbEncoded
, cbEncoded
,
2866 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
2869 *pcbStructInfo
= bytesNeeded
;
2870 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2871 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2873 CRYPT_BIT_BLOB
*blob
;
2875 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2876 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2877 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2878 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_BIT_BLOB
);
2879 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
2880 lpszStructType
, pbEncoded
, cbEncoded
,
2881 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
2888 SetLastError(STATUS_ACCESS_VIOLATION
);
2892 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2896 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
2897 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2898 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2904 *pcbStructInfo
= sizeof(int);
2909 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
2910 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
2911 DWORD size
= sizeof(buf
);
2913 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
2914 if (pbEncoded
[0] != ASN_INTEGER
)
2916 SetLastError(CRYPT_E_ASN1_BADTAG
);
2920 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
2921 X509_MULTI_BYTE_INTEGER
, pbEncoded
, cbEncoded
, 0, NULL
, &buf
,
2925 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2926 pvStructInfo
, pcbStructInfo
, sizeof(int))))
2930 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2931 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2932 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
2934 /* initialize to a negative value to sign-extend */
2939 for (i
= 0; i
< blob
->cbData
; i
++)
2942 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
2944 memcpy(pvStructInfo
, &val
, sizeof(int));
2947 else if (GetLastError() == ERROR_MORE_DATA
)
2948 SetLastError(CRYPT_E_ASN1_LARGE
);
2952 SetLastError(STATUS_ACCESS_VIOLATION
);
2959 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
2960 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2961 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2964 DWORD bytesNeeded
, dataLen
;
2966 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2968 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2970 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
2972 *pcbStructInfo
= bytesNeeded
;
2973 else if (*pcbStructInfo
< bytesNeeded
)
2975 *pcbStructInfo
= bytesNeeded
;
2976 SetLastError(ERROR_MORE_DATA
);
2981 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2983 blob
->cbData
= dataLen
;
2984 assert(blob
->pbData
);
2989 for (i
= 0; i
< blob
->cbData
; i
++)
2991 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
3000 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
3001 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3002 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3010 if (pbEncoded
[0] != ASN_INTEGER
)
3012 SetLastError(CRYPT_E_ASN1_BADTAG
);
3016 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
3017 lpszStructType
, pbEncoded
, cbEncoded
,
3018 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
);
3022 *pcbStructInfo
= bytesNeeded
;
3023 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3024 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3026 CRYPT_INTEGER_BLOB
*blob
;
3028 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3029 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3030 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3031 blob
->pbData
= (BYTE
*)pvStructInfo
+
3032 sizeof(CRYPT_INTEGER_BLOB
);
3033 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
3034 lpszStructType
, pbEncoded
, cbEncoded
,
3035 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3042 SetLastError(STATUS_ACCESS_VIOLATION
);
3049 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
3050 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
3051 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
3052 void *pvStructInfo
, DWORD
*pcbStructInfo
)
3056 if (pbEncoded
[0] == ASN_INTEGER
)
3058 DWORD bytesNeeded
, dataLen
;
3060 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3062 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3064 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
3066 *pcbStructInfo
= bytesNeeded
;
3067 else if (*pcbStructInfo
< bytesNeeded
)
3069 *pcbStructInfo
= bytesNeeded
;
3070 SetLastError(ERROR_MORE_DATA
);
3075 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3077 blob
->cbData
= dataLen
;
3078 assert(blob
->pbData
);
3079 /* remove leading zero byte if it exists */
3080 if (blob
->cbData
&& *(pbEncoded
+ 1 + lenBytes
) == 0)
3089 for (i
= 0; i
< blob
->cbData
; i
++)
3091 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
3100 SetLastError(CRYPT_E_ASN1_BADTAG
);
3106 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType
,
3107 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3108 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3116 if ((ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
3117 lpszStructType
, pbEncoded
, cbEncoded
,
3118 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
3121 *pcbStructInfo
= bytesNeeded
;
3122 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3123 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3125 CRYPT_INTEGER_BLOB
*blob
;
3127 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3128 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3129 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3130 blob
->pbData
= (BYTE
*)pvStructInfo
+
3131 sizeof(CRYPT_INTEGER_BLOB
);
3132 ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
3133 lpszStructType
, pbEncoded
, cbEncoded
,
3134 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3141 SetLastError(STATUS_ACCESS_VIOLATION
);
3148 static BOOL WINAPI
CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType
,
3149 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3150 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3156 *pcbStructInfo
= sizeof(int);
3161 if (pbEncoded
[0] == ASN_ENUMERATED
)
3163 unsigned int val
= 0, i
;
3167 SetLastError(CRYPT_E_ASN1_EOD
);
3170 else if (pbEncoded
[1] == 0)
3172 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3177 /* A little strange looking, but we have to accept a sign byte:
3178 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3179 * assuming a small length is okay here, it has to be in short
3182 if (pbEncoded
[1] > sizeof(unsigned int) + 1)
3184 SetLastError(CRYPT_E_ASN1_LARGE
);
3187 for (i
= 0; i
< pbEncoded
[1]; i
++)
3190 val
|= pbEncoded
[2 + i
];
3192 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3193 pvStructInfo
, pcbStructInfo
, sizeof(unsigned int))))
3195 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3196 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3197 memcpy(pvStructInfo
, &val
, sizeof(unsigned int));
3203 SetLastError(CRYPT_E_ASN1_BADTAG
);
3209 SetLastError(STATUS_ACCESS_VIOLATION
);
3216 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3219 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3224 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3226 if (!isdigit(*(pbEncoded))) \
3228 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3234 (word) += *(pbEncoded)++ - '0'; \
3239 static BOOL
CRYPT_AsnDecodeTimeZone(const BYTE
*pbEncoded
, DWORD len
,
3240 SYSTEMTIME
*sysTime
)
3247 if (len
>= 3 && (*pbEncoded
== '+' || *pbEncoded
== '-'))
3249 WORD hours
, minutes
= 0;
3250 BYTE sign
= *pbEncoded
++;
3253 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, hours
);
3254 if (ret
&& hours
>= 24)
3256 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3261 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, minutes
);
3262 if (ret
&& minutes
>= 60)
3264 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3272 sysTime
->wHour
+= hours
;
3273 sysTime
->wMinute
+= minutes
;
3277 if (hours
> sysTime
->wHour
)
3280 sysTime
->wHour
= 24 - (hours
- sysTime
->wHour
);
3283 sysTime
->wHour
-= hours
;
3284 if (minutes
> sysTime
->wMinute
)
3287 sysTime
->wMinute
= 60 - (minutes
- sysTime
->wMinute
);
3290 sysTime
->wMinute
-= minutes
;
3297 SetLastError(STATUS_ACCESS_VIOLATION
);
3304 #define MIN_ENCODED_TIME_LENGTH 10
3306 static BOOL WINAPI
CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType
,
3307 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3308 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3314 *pcbStructInfo
= sizeof(FILETIME
);
3320 if (pbEncoded
[0] == ASN_UTCTIME
)
3324 SetLastError(CRYPT_E_ASN1_EOD
);
3327 else if (pbEncoded
[1] > 0x7f)
3329 /* long-form date strings really can't be valid */
3330 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3335 SYSTEMTIME sysTime
= { 0 };
3336 BYTE len
= pbEncoded
[1];
3338 if (len
< MIN_ENCODED_TIME_LENGTH
)
3340 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3346 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wYear
);
3347 if (sysTime
.wYear
>= 50)
3348 sysTime
.wYear
+= 1900;
3350 sysTime
.wYear
+= 2000;
3351 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
3352 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
3353 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
3354 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMinute
);
3357 if (len
>= 2 && isdigit(*pbEncoded
) &&
3358 isdigit(*(pbEncoded
+ 1)))
3359 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3361 else if (isdigit(*pbEncoded
))
3362 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 1,
3365 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
3368 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3369 pDecodePara
, pvStructInfo
, pcbStructInfo
,
3372 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3373 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3374 ret
= SystemTimeToFileTime(&sysTime
,
3375 (FILETIME
*)pvStructInfo
);
3382 SetLastError(CRYPT_E_ASN1_BADTAG
);
3388 SetLastError(STATUS_ACCESS_VIOLATION
);
3395 static BOOL WINAPI
CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType
,
3396 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3397 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3403 *pcbStructInfo
= sizeof(FILETIME
);
3409 if (pbEncoded
[0] == ASN_GENERALTIME
)
3413 SetLastError(CRYPT_E_ASN1_EOD
);
3416 else if (pbEncoded
[1] > 0x7f)
3418 /* long-form date strings really can't be valid */
3419 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3424 BYTE len
= pbEncoded
[1];
3426 if (len
< MIN_ENCODED_TIME_LENGTH
)
3428 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3433 SYSTEMTIME sysTime
= { 0 };
3436 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 4, sysTime
.wYear
);
3437 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
3438 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
3439 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
3442 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3445 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3447 if (ret
&& len
> 0 && (*pbEncoded
== '.' ||
3454 /* workaround macro weirdness */
3455 digits
= min(len
, 3);
3456 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, digits
,
3457 sysTime
.wMilliseconds
);
3460 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
3463 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3464 pDecodePara
, pvStructInfo
, pcbStructInfo
,
3467 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3468 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3469 ret
= SystemTimeToFileTime(&sysTime
,
3470 (FILETIME
*)pvStructInfo
);
3477 SetLastError(CRYPT_E_ASN1_BADTAG
);
3483 SetLastError(STATUS_ACCESS_VIOLATION
);
3490 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
3491 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3492 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3498 if (pbEncoded
[0] == ASN_UTCTIME
)
3499 ret
= CRYPT_AsnDecodeUtcTime(dwCertEncodingType
, lpszStructType
,
3500 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
3502 else if (pbEncoded
[0] == ASN_GENERALTIME
)
3503 ret
= CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType
,
3504 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
,
3505 pvStructInfo
, pcbStructInfo
);
3508 SetLastError(CRYPT_E_ASN1_BADTAG
);
3514 SetLastError(STATUS_ACCESS_VIOLATION
);
3521 static BOOL WINAPI
CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType
,
3522 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3523 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3529 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3531 DWORD bytesNeeded
, dataLen
, remainingLen
, cValue
;
3533 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3538 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3539 bytesNeeded
= sizeof(CRYPT_SEQUENCE_OF_ANY
);
3541 ptr
= pbEncoded
+ 1 + lenBytes
;
3542 remainingLen
= dataLen
;
3543 while (ret
&& remainingLen
)
3547 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
3550 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
3552 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
3553 ptr
+= 1 + nextLenBytes
+ nextLen
;
3554 bytesNeeded
+= sizeof(CRYPT_DER_BLOB
);
3555 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3556 bytesNeeded
+= 1 + nextLenBytes
+ nextLen
;
3562 CRYPT_SEQUENCE_OF_ANY
*seq
;
3566 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3567 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3569 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3570 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3571 seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
3572 seq
->cValue
= cValue
;
3573 seq
->rgValue
= (CRYPT_DER_BLOB
*)((BYTE
*)seq
+
3575 nextPtr
= (BYTE
*)seq
->rgValue
+
3576 cValue
* sizeof(CRYPT_DER_BLOB
);
3577 ptr
= pbEncoded
+ 1 + lenBytes
;
3578 remainingLen
= dataLen
;
3580 while (ret
&& remainingLen
)
3584 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
3587 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
3589 seq
->rgValue
[i
].cbData
= 1 + nextLenBytes
+
3591 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3592 seq
->rgValue
[i
].pbData
= (BYTE
*)ptr
;
3595 seq
->rgValue
[i
].pbData
= nextPtr
;
3596 memcpy(nextPtr
, ptr
, 1 + nextLenBytes
+
3598 nextPtr
+= 1 + nextLenBytes
+ nextLen
;
3600 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
3601 ptr
+= 1 + nextLenBytes
+ nextLen
;
3611 SetLastError(CRYPT_E_ASN1_BADTAG
);
3617 SetLastError(STATUS_ACCESS_VIOLATION
);
3624 static BOOL WINAPI
CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType
,
3625 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3626 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3630 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0))
3632 DWORD bytesNeeded
, dataLen
;
3634 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3636 struct AsnArrayDescriptor arrayDesc
= {
3637 ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, CRYPT_AsnDecodeAltNameEntry
,
3638 sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
3639 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
3640 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3646 ret
= CRYPT_AsnDecodeArray(&arrayDesc
,
3647 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
3648 0, NULL
, NULL
, &nameLen
, NULL
);
3649 bytesNeeded
= sizeof(CRL_DIST_POINT_NAME
) + nameLen
;
3652 bytesNeeded
= sizeof(CRL_DIST_POINT_NAME
);
3654 *pcbStructInfo
= bytesNeeded
;
3655 else if (*pcbStructInfo
< bytesNeeded
)
3657 *pcbStructInfo
= bytesNeeded
;
3658 SetLastError(ERROR_MORE_DATA
);
3663 CRL_DIST_POINT_NAME
*name
= (CRL_DIST_POINT_NAME
*)pvStructInfo
;
3667 name
->dwDistPointNameChoice
= CRL_DIST_POINT_FULL_NAME
;
3668 ret
= CRYPT_AsnDecodeArray(&arrayDesc
,
3669 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
3670 0, NULL
, &name
->u
.FullName
, pcbStructInfo
,
3671 name
->u
.FullName
.rgAltEntry
);
3674 name
->dwDistPointNameChoice
= CRL_DIST_POINT_NO_NAME
;
3680 SetLastError(CRYPT_E_ASN1_BADTAG
);
3686 static BOOL WINAPI
CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType
,
3687 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3688 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3690 struct AsnDecodeSequenceItem items
[] = {
3691 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_DIST_POINT
,
3692 DistPointName
), CRYPT_AsnDecodeDistPointName
,
3693 sizeof(CRL_DIST_POINT_NAME
), TRUE
, TRUE
, offsetof(CRL_DIST_POINT
,
3694 DistPointName
.u
.FullName
.rgAltEntry
), 0 },
3695 { ASN_CONTEXT
| 1, offsetof(CRL_DIST_POINT
, ReasonFlags
),
3696 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
3697 offsetof(CRL_DIST_POINT
, ReasonFlags
.pbData
), 0 },
3698 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2, offsetof(CRL_DIST_POINT
, CRLIssuer
),
3699 CRYPT_AsnDecodeAltNameInternal
, sizeof(CERT_ALT_NAME_INFO
), TRUE
, TRUE
,
3700 offsetof(CRL_DIST_POINT
, CRLIssuer
.rgAltEntry
), 0 },
3704 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3705 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
3706 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3710 static BOOL WINAPI
CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType
,
3711 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3712 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3716 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3717 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3721 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3722 CRYPT_AsnDecodeDistPoint
, sizeof(CRL_DIST_POINT
), TRUE
,
3723 offsetof(CRL_DIST_POINT
, DistPointName
.u
.FullName
.rgAltEntry
) };
3725 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3726 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3730 SetLastError(STATUS_ACCESS_VIOLATION
);
3737 static BOOL WINAPI
CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3738 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3739 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3743 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3744 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3748 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3749 CRYPT_AsnDecodeOidInternal
, sizeof(LPSTR
), TRUE
, 0 };
3751 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3752 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3756 SetLastError(STATUS_ACCESS_VIOLATION
);
3763 static BOOL WINAPI
CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType
,
3764 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3765 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3769 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3770 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3774 struct AsnDecodeSequenceItem items
[] = {
3775 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_ISSUING_DIST_POINT
,
3776 DistPointName
), CRYPT_AsnDecodeDistPointName
,
3777 sizeof(CRL_DIST_POINT_NAME
), TRUE
, TRUE
,
3778 offsetof(CRL_ISSUING_DIST_POINT
,
3779 DistPointName
.u
.FullName
.rgAltEntry
), 0 },
3780 { ASN_CONTEXT
| 1, offsetof(CRL_ISSUING_DIST_POINT
,
3781 fOnlyContainsUserCerts
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
,
3783 { ASN_CONTEXT
| 2, offsetof(CRL_ISSUING_DIST_POINT
,
3784 fOnlyContainsCACerts
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
,
3786 { ASN_CONTEXT
| 3, offsetof(CRL_ISSUING_DIST_POINT
,
3787 OnlySomeReasonFlags
), CRYPT_AsnDecodeBitsInternal
,
3788 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CRL_ISSUING_DIST_POINT
,
3789 OnlySomeReasonFlags
.pbData
), 0 },
3790 { ASN_CONTEXT
| 4, offsetof(CRL_ISSUING_DIST_POINT
,
3791 fIndirectCRL
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
, FALSE
, 0 },
3794 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3795 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
3796 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3800 SetLastError(STATUS_ACCESS_VIOLATION
);
3807 static BOOL WINAPI
CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType
,
3808 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3809 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3812 struct AsnDecodeSequenceItem items
[] = {
3813 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER
, Issuer
), CRYPT_AsnDecodeDerBlob
,
3814 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_ISSUER_SERIAL_NUMBER
,
3816 { ASN_INTEGER
, offsetof(CERT_ISSUER_SERIAL_NUMBER
, SerialNumber
),
3817 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
,
3818 TRUE
, offsetof(CERT_ISSUER_SERIAL_NUMBER
, SerialNumber
.pbData
), 0 },
3820 CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
=
3821 (CERT_ISSUER_SERIAL_NUMBER
*)pvStructInfo
;
3823 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3824 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3826 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3827 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
3828 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
,
3829 issuerSerial
? issuerSerial
->Issuer
.pbData
: NULL
);
3830 if (ret
&& issuerSerial
&& !issuerSerial
->SerialNumber
.cbData
)
3832 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3835 TRACE("returning %d\n", ret
);
3839 static BOOL WINAPI
CRYPT_AsnDecodePKCSSignerInfoInternal(
3840 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
3841 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
3842 void *pvStructInfo
, DWORD
*pcbStructInfo
)
3844 CMSG_SIGNER_INFO
*info
= (CMSG_SIGNER_INFO
*)pvStructInfo
;
3845 struct AsnDecodeSequenceItem items
[] = {
3846 { ASN_INTEGER
, offsetof(CMSG_SIGNER_INFO
, dwVersion
),
3847 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
3848 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, Issuer
),
3849 CRYPT_AsnDecodeIssuerSerialNumber
, sizeof(CERT_ISSUER_SERIAL_NUMBER
),
3850 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, Issuer
.pbData
), 0 },
3851 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, HashAlgorithm
),
3852 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3853 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, HashAlgorithm
.pszObjId
), 0 },
3854 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0,
3855 offsetof(CMSG_SIGNER_INFO
, AuthAttrs
),
3856 CRYPT_AsnDecodePKCSAttributesInternal
, sizeof(CRYPT_ATTRIBUTES
),
3857 TRUE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, AuthAttrs
.rgAttr
), 0 },
3858 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, HashEncryptionAlgorithm
),
3859 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3860 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
,
3861 HashEncryptionAlgorithm
.pszObjId
), 0 },
3862 { ASN_OCTETSTRING
, offsetof(CMSG_SIGNER_INFO
, EncryptedHash
),
3863 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_DER_BLOB
),
3864 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, EncryptedHash
.pbData
), 0 },
3865 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
3866 offsetof(CMSG_SIGNER_INFO
, UnauthAttrs
),
3867 CRYPT_AsnDecodePKCSAttributesInternal
, sizeof(CRYPT_ATTRIBUTES
),
3868 TRUE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, UnauthAttrs
.rgAttr
), 0 },
3872 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3873 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3875 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3876 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
3877 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
,
3878 info
? info
->Issuer
.pbData
: NULL
);
3882 static BOOL WINAPI
CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType
,
3883 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3884 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3888 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3889 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3893 ret
= CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType
,
3894 lpszStructType
, pbEncoded
, cbEncoded
,
3895 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
3896 if (ret
&& pvStructInfo
)
3898 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
3899 pcbStructInfo
, *pcbStructInfo
);
3902 CMSG_SIGNER_INFO
*info
;
3904 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3905 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3906 info
= (CMSG_SIGNER_INFO
*)pvStructInfo
;
3907 info
->Issuer
.pbData
= ((BYTE
*)info
+
3908 sizeof(CMSG_SIGNER_INFO
));
3909 ret
= CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType
,
3910 lpszStructType
, pbEncoded
, cbEncoded
,
3911 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3918 SetLastError(STATUS_ACCESS_VIOLATION
);
3921 TRACE("returning %d\n", ret
);
3925 static BOOL WINAPI
CRYPT_DecodeSignerArray(DWORD dwCertEncodingType
,
3926 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3927 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3930 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
3931 CRYPT_AsnDecodePKCSSignerInfoInternal
, sizeof(CMSG_SIGNER_INFO
), TRUE
,
3932 offsetof(CMSG_SIGNER_INFO
, Issuer
.pbData
) };
3933 struct GenericArray
*array
= (struct GenericArray
*)pvStructInfo
;
3935 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3936 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3938 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3939 pDecodePara
, pvStructInfo
, pcbStructInfo
, array
? array
->rgItems
: NULL
);
3943 BOOL
CRYPT_AsnDecodePKCSSignedInfo(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3944 DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
3945 CRYPT_SIGNED_INFO
*signedInfo
, DWORD
*pcbSignedInfo
)
3948 struct AsnDecodeSequenceItem items
[] = {
3949 { ASN_INTEGER
, offsetof(CRYPT_SIGNED_INFO
, version
), CRYPT_AsnDecodeInt
,
3950 sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
3951 /* Placeholder for the hash algorithms - redundant with those in the
3952 * signers, so just ignore them.
3954 { ASN_CONSTRUCTOR
| ASN_SETOF
, 0, NULL
, 0, TRUE
, FALSE
, 0, 0 },
3955 { ASN_SEQUENCE
, offsetof(CRYPT_SIGNED_INFO
, content
),
3956 CRYPT_AsnDecodePKCSContentInfoInternal
, sizeof(CRYPT_CONTENT_INFO
),
3957 FALSE
, TRUE
, offsetof(CRYPT_SIGNED_INFO
, content
.pszObjId
), 0 },
3958 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0,
3959 offsetof(CRYPT_SIGNED_INFO
, cCertEncoded
),
3960 CRYPT_DecodeDERArray
, sizeof(struct GenericArray
), TRUE
, TRUE
,
3961 offsetof(CRYPT_SIGNED_INFO
, rgCertEncoded
), 0 },
3962 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
3963 offsetof(CRYPT_SIGNED_INFO
, cCrlEncoded
), CRYPT_DecodeDERArray
,
3964 sizeof(struct GenericArray
), TRUE
, TRUE
,
3965 offsetof(CRYPT_SIGNED_INFO
, rgCrlEncoded
), 0 },
3966 { ASN_CONSTRUCTOR
| ASN_SETOF
, offsetof(CRYPT_SIGNED_INFO
, cSignerInfo
),
3967 CRYPT_DecodeSignerArray
, sizeof(struct GenericArray
), TRUE
, TRUE
,
3968 offsetof(CRYPT_SIGNED_INFO
, rgSignerInfo
), 0 },
3971 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3972 pDecodePara
, signedInfo
, *pcbSignedInfo
);
3974 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3975 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3976 pDecodePara
, signedInfo
, pcbSignedInfo
, NULL
);
3977 TRACE("returning %d\n", ret
);
3981 static CryptDecodeObjectExFunc
CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType
,
3982 LPCSTR lpszStructType
)
3984 CryptDecodeObjectExFunc decodeFunc
= NULL
;
3986 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
3987 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
3989 SetLastError(ERROR_FILE_NOT_FOUND
);
3992 if (!HIWORD(lpszStructType
))
3994 switch (LOWORD(lpszStructType
))
3996 case (WORD
)X509_CERT
:
3997 decodeFunc
= CRYPT_AsnDecodeCertSignedContent
;
3999 case (WORD
)X509_CERT_TO_BE_SIGNED
:
4000 decodeFunc
= CRYPT_AsnDecodeCert
;
4002 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
4003 decodeFunc
= CRYPT_AsnDecodeCRL
;
4005 case (WORD
)X509_EXTENSIONS
:
4006 decodeFunc
= CRYPT_AsnDecodeExtensions
;
4008 case (WORD
)X509_NAME_VALUE
:
4009 decodeFunc
= CRYPT_AsnDecodeNameValue
;
4011 case (WORD
)X509_NAME
:
4012 decodeFunc
= CRYPT_AsnDecodeName
;
4014 case (WORD
)X509_PUBLIC_KEY_INFO
:
4015 decodeFunc
= CRYPT_AsnDecodePubKeyInfo
;
4017 case (WORD
)X509_AUTHORITY_KEY_ID
:
4018 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId
;
4020 case (WORD
)X509_ALTERNATE_NAME
:
4021 decodeFunc
= CRYPT_AsnDecodeAltName
;
4023 case (WORD
)X509_BASIC_CONSTRAINTS
:
4024 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
4026 case (WORD
)X509_BASIC_CONSTRAINTS2
:
4027 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
4029 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
4030 decodeFunc
= CRYPT_AsnDecodeRsaPubKey
;
4032 case (WORD
)X509_UNICODE_NAME
:
4033 decodeFunc
= CRYPT_AsnDecodeUnicodeName
;
4035 case (WORD
)PKCS_ATTRIBUTE
:
4036 decodeFunc
= CRYPT_AsnDecodePKCSAttribute
;
4038 case (WORD
)X509_UNICODE_NAME_VALUE
:
4039 decodeFunc
= CRYPT_AsnDecodeUnicodeNameValue
;
4041 case (WORD
)X509_OCTET_STRING
:
4042 decodeFunc
= CRYPT_AsnDecodeOctets
;
4044 case (WORD
)X509_BITS
:
4045 case (WORD
)X509_KEY_USAGE
:
4046 decodeFunc
= CRYPT_AsnDecodeBits
;
4048 case (WORD
)X509_INTEGER
:
4049 decodeFunc
= CRYPT_AsnDecodeInt
;
4051 case (WORD
)X509_MULTI_BYTE_INTEGER
:
4052 decodeFunc
= CRYPT_AsnDecodeInteger
;
4054 case (WORD
)X509_MULTI_BYTE_UINT
:
4055 decodeFunc
= CRYPT_AsnDecodeUnsignedInteger
;
4057 case (WORD
)X509_ENUMERATED
:
4058 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
4060 case (WORD
)X509_CHOICE_OF_TIME
:
4061 decodeFunc
= CRYPT_AsnDecodeChoiceOfTime
;
4063 case (WORD
)X509_AUTHORITY_KEY_ID2
:
4064 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId2
;
4066 case (WORD
)PKCS_CONTENT_INFO
:
4067 decodeFunc
= CRYPT_AsnDecodePKCSContentInfo
;
4069 case (WORD
)X509_SEQUENCE_OF_ANY
:
4070 decodeFunc
= CRYPT_AsnDecodeSequenceOfAny
;
4072 case (WORD
)PKCS_UTC_TIME
:
4073 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
4075 case (WORD
)X509_CRL_DIST_POINTS
:
4076 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
4078 case (WORD
)X509_ENHANCED_KEY_USAGE
:
4079 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
4081 case (WORD
)PKCS_ATTRIBUTES
:
4082 decodeFunc
= CRYPT_AsnDecodePKCSAttributes
;
4084 case (WORD
)X509_ISSUING_DIST_POINT
:
4085 decodeFunc
= CRYPT_AsnDecodeIssuingDistPoint
;
4087 case (WORD
)PKCS7_SIGNER_INFO
:
4088 decodeFunc
= CRYPT_AsnDecodePKCSSignerInfo
;
4092 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4093 decodeFunc
= CRYPT_AsnDecodeExtensions
;
4094 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4095 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
4096 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4097 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId
;
4098 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4099 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId2
;
4100 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4101 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
4102 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4103 decodeFunc
= CRYPT_AsnDecodeBits
;
4104 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4105 decodeFunc
= CRYPT_AsnDecodeOctets
;
4106 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4107 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
4108 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4109 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
4110 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4111 decodeFunc
= CRYPT_AsnDecodeAltName
;
4112 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4113 decodeFunc
= CRYPT_AsnDecodeAltName
;
4114 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4115 decodeFunc
= CRYPT_AsnDecodeAltName
;
4116 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4117 decodeFunc
= CRYPT_AsnDecodeAltName
;
4118 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4119 decodeFunc
= CRYPT_AsnDecodeAltName
;
4120 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4121 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
4122 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4123 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
4124 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4125 decodeFunc
= CRYPT_AsnDecodeIssuingDistPoint
;
4129 static CryptDecodeObjectFunc
CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType
,
4130 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4132 static HCRYPTOIDFUNCSET set
= NULL
;
4133 CryptDecodeObjectFunc decodeFunc
= NULL
;
4136 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC
, 0);
4137 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4138 (void **)&decodeFunc
, hFunc
);
4142 static CryptDecodeObjectExFunc
CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType
,
4143 LPCSTR lpszStructType
, HCRYPTOIDFUNCADDR
*hFunc
)
4145 static HCRYPTOIDFUNCSET set
= NULL
;
4146 CryptDecodeObjectExFunc decodeFunc
= NULL
;
4149 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC
, 0);
4150 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4151 (void **)&decodeFunc
, hFunc
);
4155 BOOL WINAPI
CryptDecodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4156 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
,
4157 DWORD
*pcbStructInfo
)
4160 CryptDecodeObjectFunc pCryptDecodeObject
= NULL
;
4161 CryptDecodeObjectExFunc pCryptDecodeObjectEx
= NULL
;
4162 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4164 TRACE_(crypt
)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType
,
4165 debugstr_a(lpszStructType
), pbEncoded
, cbEncoded
, dwFlags
,
4166 pvStructInfo
, pcbStructInfo
);
4168 if (!pvStructInfo
&& !pcbStructInfo
)
4170 SetLastError(ERROR_INVALID_PARAMETER
);
4175 SetLastError(CRYPT_E_ASN1_EOD
);
4178 if (cbEncoded
> MAX_ENCODED_LEN
)
4180 SetLastError(CRYPT_E_ASN1_LARGE
);
4184 if (!(pCryptDecodeObjectEx
= CRYPT_GetBuiltinDecoder(dwCertEncodingType
,
4187 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4188 debugstr_a(lpszStructType
));
4189 pCryptDecodeObject
= CRYPT_LoadDecoderFunc(dwCertEncodingType
,
4190 lpszStructType
, &hFunc
);
4191 if (!pCryptDecodeObject
)
4192 pCryptDecodeObjectEx
= CRYPT_LoadDecoderExFunc(dwCertEncodingType
,
4193 lpszStructType
, &hFunc
);
4195 if (pCryptDecodeObject
)
4196 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
4197 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
4198 else if (pCryptDecodeObjectEx
)
4199 ret
= pCryptDecodeObjectEx(dwCertEncodingType
, lpszStructType
,
4200 pbEncoded
, cbEncoded
, dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
4201 pvStructInfo
, pcbStructInfo
);
4203 CryptFreeOIDFunctionAddress(hFunc
, 0);
4204 TRACE_(crypt
)("returning %d\n", ret
);
4208 BOOL WINAPI
CryptDecodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
4209 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
4210 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
4213 CryptDecodeObjectExFunc decodeFunc
;
4214 HCRYPTOIDFUNCADDR hFunc
= NULL
;
4216 TRACE_(crypt
)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4217 dwCertEncodingType
, debugstr_a(lpszStructType
), pbEncoded
,
4218 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
4220 if (!pvStructInfo
&& !pcbStructInfo
)
4222 SetLastError(ERROR_INVALID_PARAMETER
);
4227 SetLastError(CRYPT_E_ASN1_EOD
);
4230 if (cbEncoded
> MAX_ENCODED_LEN
)
4232 SetLastError(CRYPT_E_ASN1_LARGE
);
4236 SetLastError(NOERROR
);
4237 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
&& pvStructInfo
)
4238 *(BYTE
**)pvStructInfo
= NULL
;
4239 decodeFunc
= CRYPT_GetBuiltinDecoder(dwCertEncodingType
, lpszStructType
);
4242 TRACE_(crypt
)("OID %s not found or unimplemented, looking for DLL\n",
4243 debugstr_a(lpszStructType
));
4244 decodeFunc
= CRYPT_LoadDecoderExFunc(dwCertEncodingType
, lpszStructType
,
4248 ret
= decodeFunc(dwCertEncodingType
, lpszStructType
, pbEncoded
,
4249 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
4252 CryptDecodeObjectFunc pCryptDecodeObject
=
4253 CRYPT_LoadDecoderFunc(dwCertEncodingType
, lpszStructType
, &hFunc
);
4255 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4256 * directly, as that could cause an infinite loop.
4258 if (pCryptDecodeObject
)
4260 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
4262 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
4263 pbEncoded
, cbEncoded
, dwFlags
, NULL
, pcbStructInfo
);
4264 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
4265 pvStructInfo
, pcbStructInfo
, *pcbStructInfo
)))
4266 ret
= pCryptDecodeObject(dwCertEncodingType
,
4267 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
,
4268 *(BYTE
**)pvStructInfo
, pcbStructInfo
);
4271 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
4272 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
4276 CryptFreeOIDFunctionAddress(hFunc
, 0);
4277 TRACE_(crypt
)("returning %d\n", ret
);