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(crypt
);
64 typedef BOOL (WINAPI
*CryptDecodeObjectFunc
)(DWORD
, LPCSTR
, const BYTE
*,
65 DWORD
, DWORD
, void *, DWORD
*);
66 typedef BOOL (WINAPI
*CryptDecodeObjectExFunc
)(DWORD
, LPCSTR
, const BYTE
*,
67 DWORD
, DWORD
, PCRYPT_DECODE_PARA
, void *, DWORD
*);
69 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
70 * The dwCertEncodingType and lpszStructType are ignored by the built-in
71 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
72 * since it must call functions in external DLLs that follow these signatures.
74 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
75 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
76 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
77 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType
,
78 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
79 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
80 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
81 * time, doesn't do memory allocation, and doesn't do exception handling.
82 * (This isn't intended to be the externally-called one.)
84 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
85 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
86 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
87 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
88 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
89 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
90 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
91 /* Internal function */
92 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
93 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
94 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
97 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
98 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
99 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
100 * member has been initialized, doesn't do exception handling, and doesn't do
103 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
104 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
105 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
106 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
107 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
108 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
109 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
110 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
111 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
112 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
113 * member has been initialized, doesn't do exception handling, and doesn't do
114 * memory allocation. Also doesn't check tag, assumes the caller has checked
117 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
118 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
119 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
);
120 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
121 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
122 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
123 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
124 void *pvStructInfo
, DWORD
*pcbStructInfo
);
126 BOOL WINAPI
CryptDecodeObject(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
127 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
,
128 DWORD
*pcbStructInfo
)
130 static HCRYPTOIDFUNCSET set
= NULL
;
132 CryptDecodeObjectFunc pCryptDecodeObject
;
133 HCRYPTOIDFUNCADDR hFunc
;
135 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType
,
136 debugstr_a(lpszStructType
), pbEncoded
, cbEncoded
, dwFlags
,
137 pvStructInfo
, pcbStructInfo
);
139 if (!pvStructInfo
&& !pcbStructInfo
)
141 SetLastError(ERROR_INVALID_PARAMETER
);
145 /* Try registered DLL first.. */
147 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC
, 0);
148 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
149 (void **)&pCryptDecodeObject
, &hFunc
);
150 if (pCryptDecodeObject
)
152 ret
= pCryptDecodeObject(dwCertEncodingType
, lpszStructType
,
153 pbEncoded
, cbEncoded
, dwFlags
, pvStructInfo
, pcbStructInfo
);
154 CryptFreeOIDFunctionAddress(hFunc
, 0);
158 /* If not, use CryptDecodeObjectEx */
159 ret
= CryptDecodeObjectEx(dwCertEncodingType
, lpszStructType
, pbEncoded
,
160 cbEncoded
, dwFlags
, NULL
, pvStructInfo
, pcbStructInfo
);
165 /* Gets the number of length bytes from the given (leading) length byte */
166 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
168 /* Helper function to get the encoded length of the data starting at pbEncoded,
169 * where pbEncoded[0] is the tag. If the data are too short to contain a
170 * length or if the length is too large for cbEncoded, sets an appropriate
171 * error code and returns FALSE.
173 static BOOL WINAPI
CRYPT_GetLen(const BYTE
*pbEncoded
, DWORD cbEncoded
,
180 SetLastError(CRYPT_E_ASN1_CORRUPT
);
183 else if (pbEncoded
[1] <= 0x7f)
185 if (pbEncoded
[1] + 1 > cbEncoded
)
187 SetLastError(CRYPT_E_ASN1_EOD
);
196 else if (pbEncoded
[1] == 0x80)
198 FIXME("unimplemented for indefinite-length encoding\n");
199 SetLastError(CRYPT_E_ASN1_CORRUPT
);
204 BYTE lenLen
= GET_LEN_BYTES(pbEncoded
[1]);
206 if (lenLen
> sizeof(DWORD
) + 1)
208 SetLastError(CRYPT_E_ASN1_LARGE
);
211 else if (lenLen
+ 2 > cbEncoded
)
213 SetLastError(CRYPT_E_ASN1_CORRUPT
);
226 if (out
+ lenLen
+ 1 > cbEncoded
)
228 SetLastError(CRYPT_E_ASN1_EOD
);
241 /* Helper function to check *pcbStructInfo, set it to the required size, and
242 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
243 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
244 * pointer to the newly allocated memory.
246 static BOOL
CRYPT_DecodeEnsureSpace(DWORD dwFlags
,
247 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
252 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
254 if (pDecodePara
&& pDecodePara
->pfnAlloc
)
255 *(BYTE
**)pvStructInfo
= pDecodePara
->pfnAlloc(bytesNeeded
);
257 *(BYTE
**)pvStructInfo
= LocalAlloc(0, bytesNeeded
);
258 if (!*(BYTE
**)pvStructInfo
)
261 *pcbStructInfo
= bytesNeeded
;
263 else if (*pcbStructInfo
< bytesNeeded
)
265 *pcbStructInfo
= bytesNeeded
;
266 SetLastError(ERROR_MORE_DATA
);
273 * The expected tag of the item. If tag is 0, decodeFunc is called
274 * regardless of the tag value seen.
276 * A sequence is decoded into a struct. The offset member is the
277 * offset of this item within that struct.
279 * The decoder function to use. If this is NULL, then the member isn't
280 * decoded, but minSize space is reserved for it.
282 * The minimum amount of space occupied after decoding. You must set this.
284 * If true, and the tag doesn't match the expected tag for this item,
285 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
286 * filled with 0 for this member.
287 * hasPointer, pointerOffset:
288 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
289 * the offset within the struct of the data pointer (or to the
290 * first data pointer, if more than one exist).
292 * Used by CRYPT_AsnDecodeSequence, not for your use.
294 struct AsnDecodeSequenceItem
298 CryptDecodeObjectExFunc decodeFunc
;
306 /* Decodes the items in a sequence, where the items are described in items,
307 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
308 * pvStructInfo. nextData is a pointer to the memory location at which the
309 * first decoded item with a dynamic pointer should point.
310 * Upon decoding, *cbDecoded is the total number of bytes decoded.
312 static BOOL
CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType
,
313 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
314 DWORD cbEncoded
, DWORD dwFlags
, void *pvStructInfo
, BYTE
*nextData
,
318 DWORD i
, decoded
= 0;
319 const BYTE
*ptr
= pbEncoded
;
321 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items
, cItem
, pbEncoded
,
322 cbEncoded
, dwFlags
, pvStructInfo
, nextData
, cbDecoded
);
324 for (i
= 0, ret
= TRUE
; ret
&& i
< cItem
; i
++)
326 if (cbEncoded
- (ptr
- pbEncoded
) != 0)
330 if ((ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
333 BYTE nextItemLenBytes
= GET_LEN_BYTES(ptr
[1]);
335 if (ptr
[0] == items
[i
].tag
|| !items
[i
].tag
)
337 if (nextData
&& pvStructInfo
&& items
[i
].hasPointer
)
339 TRACE("Setting next pointer to %p\n",
341 *(BYTE
**)((BYTE
*)pvStructInfo
+
342 items
[i
].pointerOffset
) = nextData
;
344 if (items
[i
].decodeFunc
)
347 TRACE("decoding item %d\n", i
);
349 TRACE("sizing item %d\n", i
);
350 ret
= items
[i
].decodeFunc(dwCertEncodingType
,
351 NULL
, ptr
, 1 + nextItemLenBytes
+ nextItemLen
,
352 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
353 pvStructInfo
? (BYTE
*)pvStructInfo
+ items
[i
].offset
354 : NULL
, &items
[i
].size
);
357 /* Account for alignment padding */
358 if (items
[i
].size
% sizeof(DWORD
))
359 items
[i
].size
+= sizeof(DWORD
) -
360 items
[i
].size
% sizeof(DWORD
);
361 TRACE("item %d size: %d\n", i
, items
[i
].size
);
362 if (nextData
&& items
[i
].hasPointer
&&
363 items
[i
].size
> items
[i
].minSize
)
364 nextData
+= items
[i
].size
- items
[i
].minSize
;
365 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
366 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
367 TRACE("item %d: decoded %d bytes\n", i
,
368 1 + nextItemLenBytes
+ nextItemLen
);
370 else if (items
[i
].optional
&&
371 GetLastError() == CRYPT_E_ASN1_BADTAG
)
373 TRACE("skipping optional item %d\n", i
);
374 items
[i
].size
= items
[i
].minSize
;
375 SetLastError(NOERROR
);
379 TRACE("item %d failed: %08x\n", i
,
384 TRACE("item %d: decoded %d bytes\n", i
,
385 1 + nextItemLenBytes
+ nextItemLen
);
386 ptr
+= 1 + nextItemLenBytes
+ nextItemLen
;
387 decoded
+= 1 + nextItemLenBytes
+ nextItemLen
;
388 items
[i
].size
= items
[i
].minSize
;
391 else if (items
[i
].optional
)
393 TRACE("skipping optional item %d\n", i
);
394 items
[i
].size
= items
[i
].minSize
;
398 TRACE("item %d: tag %02x doesn't match expected %02x\n",
399 i
, ptr
[0], items
[i
].tag
);
400 SetLastError(CRYPT_E_ASN1_BADTAG
);
405 else if (items
[i
].optional
)
407 TRACE("missing optional item %d, skipping\n", i
);
408 items
[i
].size
= items
[i
].minSize
;
412 TRACE("not enough bytes for item %d, failing\n", i
);
413 SetLastError(CRYPT_E_ASN1_CORRUPT
);
418 *cbDecoded
= decoded
;
419 TRACE("returning %d\n", ret
);
423 /* This decodes an arbitrary sequence into a contiguous block of memory
424 * (basically, a struct.) Each element being decoded is described by a struct
425 * AsnDecodeSequenceItem, see above.
426 * startingPointer is an optional pointer to the first place where dynamic
427 * data will be stored. If you know the starting offset, you may pass it
428 * here. Otherwise, pass NULL, and one will be inferred from the items.
429 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
431 static BOOL
CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType
,
432 struct AsnDecodeSequenceItem items
[], DWORD cItem
, const BYTE
*pbEncoded
,
433 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
434 void *pvStructInfo
, DWORD
*pcbStructInfo
, void *startingPointer
)
438 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items
, cItem
, pbEncoded
,
439 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
442 if (pbEncoded
[0] == ASN_SEQUENCE
)
446 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
448 DWORD lenBytes
= GET_LEN_BYTES(pbEncoded
[1]), cbDecoded
;
449 const BYTE
*ptr
= pbEncoded
+ 1 + lenBytes
;
451 cbEncoded
-= 1 + lenBytes
;
452 if (cbEncoded
< dataLen
)
454 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen
,
456 SetLastError(CRYPT_E_ASN1_CORRUPT
);
460 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
, ptr
,
461 cbEncoded
, dwFlags
, NULL
, NULL
, &cbDecoded
);
462 if (ret
&& cbDecoded
!= dataLen
)
464 TRACE("expected %d decoded, got %d, failing\n", dataLen
,
466 SetLastError(CRYPT_E_ASN1_CORRUPT
);
471 DWORD i
, bytesNeeded
= 0, structSize
= 0;
473 for (i
= 0; i
< cItem
; i
++)
475 bytesNeeded
+= items
[i
].size
;
476 structSize
+= items
[i
].minSize
;
479 *pcbStructInfo
= bytesNeeded
;
480 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
481 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
485 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
486 pvStructInfo
= *(BYTE
**)pvStructInfo
;
488 nextData
= (BYTE
*)startingPointer
;
490 nextData
= (BYTE
*)pvStructInfo
+ structSize
;
491 memset(pvStructInfo
, 0, structSize
);
492 ret
= CRYPT_AsnDecodeSequenceItems(dwFlags
, items
, cItem
,
493 ptr
, cbEncoded
, dwFlags
, pvStructInfo
, nextData
,
501 SetLastError(CRYPT_E_ASN1_BADTAG
);
504 TRACE("returning %d (%08x)\n", ret
, GetLastError());
509 * The expected tag of the entire encoded array (usually a variant
510 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
511 * regardless of the tag seen.
513 * used to decode each item in the array
515 * is the minimum size of each decoded item
517 * indicates whether each item has a dynamic pointer
519 * indicates the offset within itemSize at which the pointer exists
521 struct AsnArrayDescriptor
524 CryptDecodeObjectExFunc decodeFunc
;
530 struct AsnArrayItemSize
536 /* Decodes an array of like types into a struct GenericArray.
537 * The layout and decoding of the array are described by a struct
538 * AsnArrayDescriptor.
540 static BOOL
CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor
*arrayDesc
,
541 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
542 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
,
543 void *startingPointer
)
547 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc
, pbEncoded
,
548 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, *pcbStructInfo
,
551 if (!arrayDesc
->tag
|| pbEncoded
[0] == arrayDesc
->tag
)
555 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
557 DWORD bytesNeeded
, cItems
= 0;
558 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
559 /* There can be arbitrarily many items, but there is often only one.
561 struct AsnArrayItemSize itemSize
= { 0 }, *itemSizes
= &itemSize
;
563 bytesNeeded
= sizeof(struct GenericArray
);
568 for (ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
569 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
571 DWORD itemLenBytes
, itemDataLen
, size
= 0;
573 itemLenBytes
= GET_LEN_BYTES(ptr
[1]);
574 /* Each item decoded may not tolerate extraneous bytes, so
575 * get the length of the next element and pass it directly.
577 ret
= CRYPT_GetLen(ptr
, cbEncoded
- (ptr
- pbEncoded
),
580 ret
= arrayDesc
->decodeFunc(X509_ASN_ENCODING
, 0, ptr
,
581 1 + itemLenBytes
+ itemDataLen
,
582 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
,
589 if (itemSizes
!= &itemSize
)
590 itemSizes
= CryptMemRealloc(itemSizes
,
591 cItems
* sizeof(struct AsnArrayItemSize
));
596 cItems
* sizeof(struct AsnArrayItemSize
));
598 memcpy(itemSizes
, &itemSize
, sizeof(itemSize
));
602 itemSizes
[cItems
- 1].encodedLen
= 1 + itemLenBytes
604 itemSizes
[cItems
- 1].size
= size
;
606 ret
= CRYPT_GetLen(ptr
,
607 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
609 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
619 *pcbStructInfo
= bytesNeeded
;
620 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
621 pDecodePara
, pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
626 struct GenericArray
*array
;
628 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
629 pvStructInfo
= *(BYTE
**)pvStructInfo
;
630 array
= (struct GenericArray
*)pvStructInfo
;
631 array
->cItems
= cItems
;
633 array
->rgItems
= startingPointer
;
635 array
->rgItems
= (BYTE
*)array
+
636 sizeof(struct GenericArray
);
637 nextData
= (BYTE
*)array
->rgItems
+
638 array
->cItems
* arrayDesc
->itemSize
;
639 for (i
= 0, ptr
= pbEncoded
+ 1 + lenBytes
; ret
&&
640 i
< cItems
&& ptr
- pbEncoded
- 1 - lenBytes
<
643 if (arrayDesc
->hasPointer
)
644 *(BYTE
**)(array
->rgItems
+ i
* arrayDesc
->itemSize
645 + arrayDesc
->pointerOffset
) = nextData
;
646 ret
= arrayDesc
->decodeFunc(X509_ASN_ENCODING
, 0, ptr
,
647 itemSizes
[i
].encodedLen
,
648 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
,
649 array
->rgItems
+ i
* arrayDesc
->itemSize
,
655 nextData
+= itemSizes
[i
].size
- arrayDesc
->itemSize
;
656 ret
= CRYPT_GetLen(ptr
,
657 cbEncoded
- (ptr
- pbEncoded
), &nextLen
);
659 ptr
+= nextLen
+ 1 + GET_LEN_BYTES(ptr
[1]);
664 if (itemSizes
!= &itemSize
)
665 CryptMemFree(itemSizes
);
670 SetLastError(CRYPT_E_ASN1_BADTAG
);
676 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
677 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
678 * to CRYPT_E_ASN1_CORRUPT.
679 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
682 static BOOL WINAPI
CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType
,
683 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
684 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
689 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
691 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
692 DWORD bytesNeeded
= sizeof(CRYPT_DER_BLOB
);
694 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
695 bytesNeeded
+= 1 + lenBytes
+ dataLen
;
698 *pcbStructInfo
= bytesNeeded
;
699 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
700 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
702 CRYPT_DER_BLOB
*blob
;
704 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
705 pvStructInfo
= *(BYTE
**)pvStructInfo
;
706 blob
= (CRYPT_DER_BLOB
*)pvStructInfo
;
707 blob
->cbData
= 1 + lenBytes
+ dataLen
;
710 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
711 blob
->pbData
= (BYTE
*)pbEncoded
;
714 assert(blob
->pbData
);
715 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
720 SetLastError(CRYPT_E_ASN1_CORRUPT
);
728 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
729 static BOOL WINAPI
CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType
,
730 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
731 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
735 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
736 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
738 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
741 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
, lpszStructType
,
742 pbEncoded
, cbEncoded
, dwFlags
& ~CRYPT_DECODE_NOCOPY_FLAG
, pDecodePara
,
743 pvStructInfo
, pcbStructInfo
);
744 if (ret
&& pvStructInfo
)
746 CRYPT_BIT_BLOB
*blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
753 for (i
= 0; i
< blob
->cbData
/ 2; i
++)
755 temp
= blob
->pbData
[i
];
756 blob
->pbData
[i
] = blob
->pbData
[blob
->cbData
- i
- 1];
757 blob
->pbData
[blob
->cbData
- i
- 1] = temp
;
761 TRACE("returning %d (%08x)\n", ret
, GetLastError());
765 static BOOL WINAPI
CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType
,
766 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
767 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
771 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
772 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
776 struct AsnDecodeSequenceItem items
[] = {
777 { 0, offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
),
778 CRYPT_AsnDecodeDerBlob
, sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
,
779 offsetof(CERT_SIGNED_CONTENT_INFO
, ToBeSigned
.pbData
), 0 },
780 { ASN_SEQUENCEOF
, offsetof(CERT_SIGNED_CONTENT_INFO
,
781 SignatureAlgorithm
), CRYPT_AsnDecodeAlgorithmId
,
782 sizeof(CRYPT_ALGORITHM_IDENTIFIER
), FALSE
, TRUE
,
783 offsetof(CERT_SIGNED_CONTENT_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
784 { ASN_BITSTRING
, offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
),
785 CRYPT_AsnDecodeBitsSwapBytes
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
786 offsetof(CERT_SIGNED_CONTENT_INFO
, Signature
.pbData
), 0 },
789 if (dwFlags
& CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG
)
790 items
[2].decodeFunc
= CRYPT_AsnDecodeBitsInternal
;
791 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
792 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
793 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
797 SetLastError(STATUS_ACCESS_VIOLATION
);
802 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
806 /* Internal function */
807 static BOOL WINAPI
CRYPT_AsnDecodeCertVersion(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_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
819 pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
, pDecodePara
,
820 pvStructInfo
, pcbStructInfo
);
825 static BOOL WINAPI
CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType
,
826 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
827 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
831 struct AsnDecodeSequenceItem items
[] = {
832 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotBefore
),
833 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
834 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY
, NotAfter
),
835 CRYPT_AsnDecodeChoiceOfTime
, sizeof(FILETIME
), FALSE
, FALSE
, 0 },
838 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
839 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
840 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
844 /* Internal function */
845 static BOOL WINAPI
CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType
,
846 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
847 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
852 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
854 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
856 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
857 X509_EXTENSIONS
, pbEncoded
+ 1 + lenBytes
, dataLen
, dwFlags
,
858 pDecodePara
, pvStructInfo
, pcbStructInfo
);
863 static BOOL WINAPI
CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType
,
864 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
865 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
868 struct AsnDecodeSequenceItem items
[] = {
869 { ASN_CONTEXT
| ASN_CONSTRUCTOR
, offsetof(CERT_INFO
, dwVersion
),
870 CRYPT_AsnDecodeCertVersion
, sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
871 { ASN_INTEGER
, offsetof(CERT_INFO
, SerialNumber
),
872 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
,
873 TRUE
, offsetof(CERT_INFO
, SerialNumber
.pbData
), 0 },
874 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, SignatureAlgorithm
),
875 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
876 FALSE
, TRUE
, offsetof(CERT_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
877 { 0, offsetof(CERT_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
878 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
880 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, NotBefore
),
881 CRYPT_AsnDecodeValidity
, sizeof(CERT_PRIVATE_KEY_VALIDITY
), FALSE
,
883 { 0, offsetof(CERT_INFO
, Subject
), CRYPT_AsnDecodeDerBlob
,
884 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_INFO
,
886 { ASN_SEQUENCEOF
, offsetof(CERT_INFO
, SubjectPublicKeyInfo
),
887 CRYPT_AsnDecodePubKeyInfoInternal
, sizeof(CERT_PUBLIC_KEY_INFO
),
888 FALSE
, TRUE
, offsetof(CERT_INFO
,
889 SubjectPublicKeyInfo
.Algorithm
.Parameters
.pbData
), 0 },
890 { ASN_BITSTRING
, offsetof(CERT_INFO
, IssuerUniqueId
),
891 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
892 offsetof(CERT_INFO
, IssuerUniqueId
.pbData
), 0 },
893 { ASN_BITSTRING
, offsetof(CERT_INFO
, SubjectUniqueId
),
894 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
895 offsetof(CERT_INFO
, SubjectUniqueId
.pbData
), 0 },
896 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 3, offsetof(CERT_INFO
, cExtension
),
897 CRYPT_AsnDecodeCertExtensions
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
898 offsetof(CERT_INFO
, rgExtension
), 0 },
901 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
902 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
904 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
905 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
906 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
907 if (ret
&& pvStructInfo
)
911 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
912 info
= *(CERT_INFO
**)pvStructInfo
;
914 info
= (CERT_INFO
*)pvStructInfo
;
915 if (!info
->SerialNumber
.cbData
|| !info
->Issuer
.cbData
||
916 !info
->Subject
.cbData
)
918 SetLastError(CRYPT_E_ASN1_CORRUPT
);
919 /* Don't need to deallocate, because it should have failed on the
920 * first pass (and no memory was allocated.)
926 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
930 static BOOL WINAPI
CRYPT_AsnDecodeCert(DWORD dwCertEncodingType
,
931 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
932 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
936 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
937 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
941 PCERT_SIGNED_CONTENT_INFO signedCert
= NULL
;
944 /* First try to decode it as a signed cert. */
945 ret
= CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType
, X509_CERT
,
946 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
947 (BYTE
*)&signedCert
, &size
);
951 ret
= CRYPT_AsnDecodeCertInfo(dwCertEncodingType
,
952 X509_CERT_TO_BE_SIGNED
, signedCert
->ToBeSigned
.pbData
,
953 signedCert
->ToBeSigned
.cbData
, dwFlags
, pDecodePara
, pvStructInfo
,
955 LocalFree(signedCert
);
957 /* Failing that, try it as an unsigned cert */
961 ret
= CRYPT_AsnDecodeCertInfo(dwCertEncodingType
,
962 X509_CERT_TO_BE_SIGNED
, pbEncoded
, cbEncoded
, dwFlags
,
963 pDecodePara
, pvStructInfo
, pcbStructInfo
);
968 SetLastError(STATUS_ACCESS_VIOLATION
);
973 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
977 static BOOL WINAPI
CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType
,
978 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
979 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
982 struct AsnDecodeSequenceItem items
[] = {
983 { ASN_INTEGER
, offsetof(CRL_ENTRY
, SerialNumber
),
984 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
, TRUE
,
985 offsetof(CRL_ENTRY
, SerialNumber
.pbData
), 0 },
986 { 0, offsetof(CRL_ENTRY
, RevocationDate
), CRYPT_AsnDecodeChoiceOfTime
,
987 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
988 { ASN_SEQUENCEOF
, offsetof(CRL_ENTRY
, cExtension
),
989 CRYPT_AsnDecodeExtensionsInternal
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
990 offsetof(CRL_ENTRY
, rgExtension
), 0 },
992 PCRL_ENTRY entry
= (PCRL_ENTRY
)pvStructInfo
;
994 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
, entry
,
997 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
998 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
999 NULL
, entry
, pcbStructInfo
, entry
? entry
->SerialNumber
.pbData
: NULL
);
1003 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1004 * been set prior to calling.
1006 static BOOL WINAPI
CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType
,
1007 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1008 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1011 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1012 CRYPT_AsnDecodeCRLEntry
, sizeof(CRL_ENTRY
), TRUE
,
1013 offsetof(CRL_ENTRY
, SerialNumber
.pbData
) };
1014 struct GenericArray
*entries
= (struct GenericArray
*)pvStructInfo
;
1016 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1017 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1019 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1020 pDecodePara
, pvStructInfo
, pcbStructInfo
,
1021 entries
? entries
->rgItems
: NULL
);
1022 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
1026 static BOOL WINAPI
CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType
,
1027 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1028 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1030 struct AsnDecodeSequenceItem items
[] = {
1031 { ASN_INTEGER
, offsetof(CRL_INFO
, dwVersion
),
1032 CRYPT_AsnDecodeInt
, sizeof(DWORD
), TRUE
, FALSE
, 0, 0 },
1033 { ASN_SEQUENCEOF
, offsetof(CRL_INFO
, SignatureAlgorithm
),
1034 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
1035 FALSE
, TRUE
, offsetof(CRL_INFO
, SignatureAlgorithm
.pszObjId
), 0 },
1036 { 0, offsetof(CRL_INFO
, Issuer
), CRYPT_AsnDecodeDerBlob
,
1037 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CRL_INFO
,
1039 { 0, offsetof(CRL_INFO
, ThisUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
1040 sizeof(FILETIME
), FALSE
, FALSE
, 0 },
1041 { 0, offsetof(CRL_INFO
, NextUpdate
), CRYPT_AsnDecodeChoiceOfTime
,
1042 sizeof(FILETIME
), TRUE
, FALSE
, 0 },
1043 { ASN_SEQUENCEOF
, offsetof(CRL_INFO
, cCRLEntry
),
1044 CRYPT_AsnDecodeCRLEntries
, sizeof(struct GenericArray
), TRUE
, TRUE
,
1045 offsetof(CRL_INFO
, rgCRLEntry
), 0 },
1046 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_INFO
, cExtension
),
1047 CRYPT_AsnDecodeCertExtensions
, sizeof(CERT_EXTENSIONS
), TRUE
, TRUE
,
1048 offsetof(CRL_INFO
, rgExtension
), 0 },
1052 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1053 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1055 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1056 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1057 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
1059 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
1063 static BOOL WINAPI
CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType
,
1064 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1065 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1069 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1070 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1074 PCERT_SIGNED_CONTENT_INFO signedCrl
= NULL
;
1077 /* First try to decode it as a signed crl. */
1078 ret
= CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType
, X509_CERT
,
1079 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
,
1080 (BYTE
*)&signedCrl
, &size
);
1084 ret
= CRYPT_AsnDecodeCRLInfo(dwCertEncodingType
,
1085 X509_CERT_CRL_TO_BE_SIGNED
, signedCrl
->ToBeSigned
.pbData
,
1086 signedCrl
->ToBeSigned
.cbData
, dwFlags
, pDecodePara
,
1087 pvStructInfo
, pcbStructInfo
);
1088 LocalFree(signedCrl
);
1090 /* Failing that, try it as an unsigned crl */
1094 ret
= CRYPT_AsnDecodeCRLInfo(dwCertEncodingType
,
1095 X509_CERT_CRL_TO_BE_SIGNED
, pbEncoded
, cbEncoded
,
1096 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
1101 SetLastError(STATUS_ACCESS_VIOLATION
);
1106 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
1110 static BOOL WINAPI
CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType
,
1111 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1112 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1117 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1118 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1120 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1122 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1123 DWORD bytesNeeded
= sizeof(LPSTR
);
1127 /* The largest possible string for the first two components
1128 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1133 snprintf(firstTwo
, sizeof(firstTwo
), "%d.%d",
1134 pbEncoded
[1 + lenBytes
] / 40,
1135 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] / 40)
1137 bytesNeeded
+= strlen(firstTwo
) + 1;
1138 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1139 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1141 /* large enough for ".4000000" */
1145 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1152 if (ptr
- pbEncoded
- 1 - lenBytes
>= dataLen
||
1155 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1162 snprintf(str
, sizeof(str
), ".%d", val
);
1163 bytesNeeded
+= strlen(str
);
1168 *pcbStructInfo
= bytesNeeded
;
1169 else if (*pcbStructInfo
< bytesNeeded
)
1171 *pcbStructInfo
= bytesNeeded
;
1172 SetLastError(ERROR_MORE_DATA
);
1180 LPSTR pszObjId
= *(LPSTR
*)pvStructInfo
;
1183 sprintf(pszObjId
, "%d.%d", pbEncoded
[1 + lenBytes
] / 40,
1184 pbEncoded
[1 + lenBytes
] - (pbEncoded
[1 + lenBytes
] /
1186 pszObjId
+= strlen(pszObjId
);
1187 for (ptr
= pbEncoded
+ 2 + lenBytes
; ret
&&
1188 ptr
- pbEncoded
- 1 - lenBytes
< dataLen
; )
1192 while (ptr
- pbEncoded
- 1 - lenBytes
< dataLen
&&
1201 sprintf(pszObjId
, ".%d", val
);
1202 pszObjId
+= strlen(pszObjId
);
1206 *(LPSTR
*)pvStructInfo
= NULL
;
1207 *pcbStructInfo
= bytesNeeded
;
1213 static BOOL WINAPI
CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType
,
1214 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1215 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1219 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1220 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1222 if (pbEncoded
[0] == ASN_OBJECTIDENTIFIER
)
1223 ret
= CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType
, lpszStructType
,
1224 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
1228 SetLastError(CRYPT_E_ASN1_BADTAG
);
1234 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1237 static BOOL WINAPI
CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType
,
1238 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1239 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1241 struct AsnDecodeSequenceItem items
[] = {
1242 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_EXTENSION
, pszObjId
),
1243 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1244 offsetof(CERT_EXTENSION
, pszObjId
), 0 },
1245 { ASN_BOOL
, offsetof(CERT_EXTENSION
, fCritical
), CRYPT_AsnDecodeBool
,
1246 sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
1247 { ASN_OCTETSTRING
, offsetof(CERT_EXTENSION
, Value
),
1248 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_OBJID_BLOB
), FALSE
, TRUE
,
1249 offsetof(CERT_EXTENSION
, Value
.pbData
) },
1252 PCERT_EXTENSION ext
= (PCERT_EXTENSION
)pvStructInfo
;
1254 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
, ext
,
1258 TRACE("ext->pszObjId is %p\n", ext
->pszObjId
);
1259 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
1260 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
1261 ext
, pcbStructInfo
, ext
? ext
->pszObjId
: NULL
);
1263 TRACE("ext->pszObjId is %p (%s)\n", ext
->pszObjId
,
1264 debugstr_a(ext
->pszObjId
));
1265 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1269 static BOOL WINAPI
CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType
,
1270 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1271 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1274 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1275 CRYPT_AsnDecodeExtension
, sizeof(CERT_EXTENSION
), TRUE
,
1276 offsetof(CERT_EXTENSION
, pszObjId
) };
1277 PCERT_EXTENSIONS exts
= (PCERT_EXTENSIONS
)pvStructInfo
;
1279 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1280 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1282 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1283 pDecodePara
, pvStructInfo
, pcbStructInfo
, exts
? exts
->rgExtension
: NULL
);
1287 static BOOL WINAPI
CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType
,
1288 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1289 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1295 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
1296 lpszStructType
, pbEncoded
, cbEncoded
,
1297 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
1298 if (ret
&& pvStructInfo
)
1300 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
1301 pcbStructInfo
, *pcbStructInfo
);
1304 CERT_EXTENSIONS
*exts
;
1306 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1307 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1308 exts
= (CERT_EXTENSIONS
*)pvStructInfo
;
1309 exts
->rgExtension
= (CERT_EXTENSION
*)((BYTE
*)exts
+
1310 sizeof(CERT_EXTENSIONS
));
1311 ret
= CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType
,
1312 lpszStructType
, pbEncoded
, cbEncoded
,
1313 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
1320 SetLastError(STATUS_ACCESS_VIOLATION
);
1327 /* Warning: this assumes the address of value->Value.pbData is already set, in
1328 * order to avoid overwriting memory. (In some cases, it may change it, if it
1329 * doesn't copy anything to memory.) Be sure to set it correctly!
1331 static BOOL WINAPI
CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType
,
1332 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1333 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1337 CERT_NAME_VALUE
*value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1339 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1341 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1342 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
), valueType
;
1344 switch (pbEncoded
[0])
1346 case ASN_OCTETSTRING
:
1347 valueType
= CERT_RDN_OCTET_STRING
;
1348 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1349 bytesNeeded
+= dataLen
;
1351 case ASN_NUMERICSTRING
:
1352 valueType
= CERT_RDN_NUMERIC_STRING
;
1353 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1354 bytesNeeded
+= dataLen
;
1356 case ASN_PRINTABLESTRING
:
1357 valueType
= CERT_RDN_PRINTABLE_STRING
;
1358 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1359 bytesNeeded
+= dataLen
;
1362 valueType
= CERT_RDN_IA5_STRING
;
1363 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1364 bytesNeeded
+= dataLen
;
1367 valueType
= CERT_RDN_T61_STRING
;
1368 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1369 bytesNeeded
+= dataLen
;
1371 case ASN_VIDEOTEXSTRING
:
1372 valueType
= CERT_RDN_VIDEOTEX_STRING
;
1373 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1374 bytesNeeded
+= dataLen
;
1376 case ASN_GRAPHICSTRING
:
1377 valueType
= CERT_RDN_GRAPHIC_STRING
;
1378 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1379 bytesNeeded
+= dataLen
;
1381 case ASN_VISIBLESTRING
:
1382 valueType
= CERT_RDN_VISIBLE_STRING
;
1383 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1384 bytesNeeded
+= dataLen
;
1386 case ASN_GENERALSTRING
:
1387 valueType
= CERT_RDN_GENERAL_STRING
;
1388 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1389 bytesNeeded
+= dataLen
;
1391 case ASN_UNIVERSALSTRING
:
1392 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1393 SetLastError(CRYPT_E_ASN1_BADTAG
);
1396 valueType
= CERT_RDN_BMP_STRING
;
1397 bytesNeeded
+= dataLen
;
1399 case ASN_UTF8STRING
:
1400 valueType
= CERT_RDN_UTF8_STRING
;
1401 bytesNeeded
+= MultiByteToWideChar(CP_UTF8
, 0,
1402 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
, NULL
, 0) * 2;
1405 SetLastError(CRYPT_E_ASN1_BADTAG
);
1410 *pcbStructInfo
= bytesNeeded
;
1411 else if (*pcbStructInfo
< bytesNeeded
)
1413 *pcbStructInfo
= bytesNeeded
;
1414 SetLastError(ERROR_MORE_DATA
);
1419 *pcbStructInfo
= bytesNeeded
;
1420 value
->dwValueType
= valueType
;
1425 assert(value
->Value
.pbData
);
1426 switch (pbEncoded
[0])
1428 case ASN_OCTETSTRING
:
1429 case ASN_NUMERICSTRING
:
1430 case ASN_PRINTABLESTRING
:
1433 case ASN_VIDEOTEXSTRING
:
1434 case ASN_GRAPHICSTRING
:
1435 case ASN_VISIBLESTRING
:
1436 case ASN_GENERALSTRING
:
1437 value
->Value
.cbData
= dataLen
;
1440 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1441 memcpy(value
->Value
.pbData
,
1442 pbEncoded
+ 1 + lenBytes
, dataLen
);
1444 value
->Value
.pbData
= (LPBYTE
)pbEncoded
+ 1 +
1450 LPWSTR str
= (LPWSTR
)value
->Value
.pbData
;
1452 value
->Value
.cbData
= dataLen
;
1453 for (i
= 0; i
< dataLen
/ 2; i
++)
1454 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
1455 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
1458 case ASN_UTF8STRING
:
1460 LPWSTR str
= (LPWSTR
)value
->Value
.pbData
;
1462 value
->Value
.cbData
= MultiByteToWideChar(CP_UTF8
, 0,
1463 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
,
1464 str
, bytesNeeded
- sizeof(CERT_NAME_VALUE
)) * 2;
1471 value
->Value
.cbData
= 0;
1472 value
->Value
.pbData
= NULL
;
1479 static BOOL WINAPI
CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType
,
1480 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1481 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1487 ret
= CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType
,
1488 lpszStructType
, pbEncoded
, cbEncoded
,
1489 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
1490 if (ret
&& pvStructInfo
)
1492 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
1493 pcbStructInfo
, *pcbStructInfo
);
1496 CERT_NAME_VALUE
*value
;
1498 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1499 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1500 value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1501 value
->Value
.pbData
= ((BYTE
*)value
+ sizeof(CERT_NAME_VALUE
));
1502 ret
= CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType
,
1503 lpszStructType
, pbEncoded
, cbEncoded
,
1504 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
1511 SetLastError(STATUS_ACCESS_VIOLATION
);
1518 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeNameValueInternal(
1519 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
1520 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
1521 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1525 CERT_NAME_VALUE
*value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1527 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
1529 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
1530 DWORD bytesNeeded
= sizeof(CERT_NAME_VALUE
), valueType
;
1532 switch (pbEncoded
[0])
1534 case ASN_NUMERICSTRING
:
1535 valueType
= CERT_RDN_NUMERIC_STRING
;
1536 bytesNeeded
+= dataLen
* 2;
1538 case ASN_PRINTABLESTRING
:
1539 valueType
= CERT_RDN_PRINTABLE_STRING
;
1540 bytesNeeded
+= dataLen
* 2;
1543 valueType
= CERT_RDN_IA5_STRING
;
1544 bytesNeeded
+= dataLen
* 2;
1547 valueType
= CERT_RDN_T61_STRING
;
1548 bytesNeeded
+= dataLen
* 2;
1550 case ASN_VIDEOTEXSTRING
:
1551 valueType
= CERT_RDN_VIDEOTEX_STRING
;
1552 bytesNeeded
+= dataLen
* 2;
1554 case ASN_GRAPHICSTRING
:
1555 valueType
= CERT_RDN_GRAPHIC_STRING
;
1556 bytesNeeded
+= dataLen
* 2;
1558 case ASN_VISIBLESTRING
:
1559 valueType
= CERT_RDN_VISIBLE_STRING
;
1560 bytesNeeded
+= dataLen
* 2;
1562 case ASN_GENERALSTRING
:
1563 valueType
= CERT_RDN_GENERAL_STRING
;
1564 bytesNeeded
+= dataLen
* 2;
1566 case ASN_UNIVERSALSTRING
:
1567 valueType
= CERT_RDN_UNIVERSAL_STRING
;
1568 bytesNeeded
+= dataLen
/ 2;
1571 valueType
= CERT_RDN_BMP_STRING
;
1572 bytesNeeded
+= dataLen
;
1574 case ASN_UTF8STRING
:
1575 valueType
= CERT_RDN_UTF8_STRING
;
1576 bytesNeeded
+= MultiByteToWideChar(CP_UTF8
, 0,
1577 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
, NULL
, 0) * 2;
1580 SetLastError(CRYPT_E_ASN1_BADTAG
);
1585 *pcbStructInfo
= bytesNeeded
;
1586 else if (*pcbStructInfo
< bytesNeeded
)
1588 *pcbStructInfo
= bytesNeeded
;
1589 SetLastError(ERROR_MORE_DATA
);
1594 *pcbStructInfo
= bytesNeeded
;
1595 value
->dwValueType
= valueType
;
1599 LPWSTR str
= (LPWSTR
)value
->Value
.pbData
;
1601 assert(value
->Value
.pbData
);
1602 switch (pbEncoded
[0])
1604 case ASN_NUMERICSTRING
:
1605 case ASN_PRINTABLESTRING
:
1608 case ASN_VIDEOTEXSTRING
:
1609 case ASN_GRAPHICSTRING
:
1610 case ASN_VISIBLESTRING
:
1611 case ASN_GENERALSTRING
:
1612 value
->Value
.cbData
= dataLen
* 2;
1613 for (i
= 0; i
< dataLen
; i
++)
1614 str
[i
] = pbEncoded
[1 + lenBytes
+ i
];
1616 case ASN_UNIVERSALSTRING
:
1617 value
->Value
.cbData
= dataLen
/ 2;
1618 for (i
= 0; i
< dataLen
/ 4; i
++)
1619 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
+ 2] << 8)
1620 | pbEncoded
[1 + lenBytes
+ 2 * i
+ 3];
1623 value
->Value
.cbData
= dataLen
;
1624 for (i
= 0; i
< dataLen
/ 2; i
++)
1625 str
[i
] = (pbEncoded
[1 + lenBytes
+ 2 * i
] << 8) |
1626 pbEncoded
[1 + lenBytes
+ 2 * i
+ 1];
1628 case ASN_UTF8STRING
:
1629 value
->Value
.cbData
= MultiByteToWideChar(CP_UTF8
, 0,
1630 (LPCSTR
)pbEncoded
+ 1 + lenBytes
, dataLen
,
1631 str
, bytesNeeded
- sizeof(CERT_NAME_VALUE
)) * 2;
1637 value
->Value
.cbData
= 0;
1638 value
->Value
.pbData
= NULL
;
1645 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType
,
1646 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1647 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1653 ret
= CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType
,
1654 lpszStructType
, pbEncoded
, cbEncoded
,
1655 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
1656 if (ret
&& pvStructInfo
)
1658 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
1659 pcbStructInfo
, *pcbStructInfo
);
1662 CERT_NAME_VALUE
*value
;
1664 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1665 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1666 value
= (CERT_NAME_VALUE
*)pvStructInfo
;
1667 value
->Value
.pbData
= ((BYTE
*)value
+ sizeof(CERT_NAME_VALUE
));
1668 ret
= CRYPT_AsnDecodeUnicodeNameValueInternal(
1669 dwCertEncodingType
, lpszStructType
, pbEncoded
, cbEncoded
,
1670 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
1677 SetLastError(STATUS_ACCESS_VIOLATION
);
1684 static BOOL WINAPI
CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType
,
1685 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1686 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1689 struct AsnDecodeSequenceItem items
[] = {
1690 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_RDN_ATTR
, pszObjId
),
1691 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1692 offsetof(CERT_RDN_ATTR
, pszObjId
), 0 },
1693 { 0, offsetof(CERT_RDN_ATTR
, dwValueType
),
1694 CRYPT_AsnDecodeNameValueInternal
, sizeof(CERT_NAME_VALUE
),
1695 FALSE
, TRUE
, offsetof(CERT_RDN_ATTR
, Value
.pbData
), 0 },
1697 CERT_RDN_ATTR
*attr
= (CERT_RDN_ATTR
*)pvStructInfo
;
1699 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1700 pvStructInfo
, *pcbStructInfo
);
1703 TRACE("attr->pszObjId is %p\n", attr
->pszObjId
);
1704 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
1705 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
1706 attr
, pcbStructInfo
, attr
? attr
->pszObjId
: NULL
);
1709 TRACE("attr->pszObjId is %p (%s)\n", attr
->pszObjId
,
1710 debugstr_a(attr
->pszObjId
));
1711 TRACE("attr->dwValueType is %d\n", attr
->dwValueType
);
1713 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1717 static BOOL WINAPI
CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType
,
1718 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1719 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1722 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
1723 CRYPT_AsnDecodeRdnAttr
, sizeof(CERT_RDN_ATTR
), TRUE
,
1724 offsetof(CERT_RDN_ATTR
, pszObjId
) };
1725 PCERT_RDN rdn
= (PCERT_RDN
)pvStructInfo
;
1727 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1728 pDecodePara
, pvStructInfo
, pcbStructInfo
, rdn
? rdn
->rgRDNAttr
: NULL
);
1732 static BOOL WINAPI
CRYPT_AsnDecodeName(DWORD dwCertEncodingType
,
1733 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1734 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1740 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1741 CRYPT_AsnDecodeRdn
, sizeof(CERT_RDN
), TRUE
,
1742 offsetof(CERT_RDN
, rgRDNAttr
) };
1744 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1745 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
1749 SetLastError(STATUS_ACCESS_VIOLATION
);
1756 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType
,
1757 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1758 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1761 struct AsnDecodeSequenceItem items
[] = {
1762 { ASN_OBJECTIDENTIFIER
, offsetof(CERT_RDN_ATTR
, pszObjId
),
1763 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1764 offsetof(CERT_RDN_ATTR
, pszObjId
), 0 },
1765 { 0, offsetof(CERT_RDN_ATTR
, dwValueType
),
1766 CRYPT_AsnDecodeUnicodeNameValueInternal
, sizeof(CERT_NAME_VALUE
),
1767 FALSE
, TRUE
, offsetof(CERT_RDN_ATTR
, Value
.pbData
), 0 },
1769 CERT_RDN_ATTR
*attr
= (CERT_RDN_ATTR
*)pvStructInfo
;
1771 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1772 pvStructInfo
, *pcbStructInfo
);
1775 TRACE("attr->pszObjId is %p\n", attr
->pszObjId
);
1776 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
1777 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
, NULL
,
1778 attr
, pcbStructInfo
, attr
? attr
->pszObjId
: NULL
);
1781 TRACE("attr->pszObjId is %p (%s)\n", attr
->pszObjId
,
1782 debugstr_a(attr
->pszObjId
));
1783 TRACE("attr->dwValueType is %d\n", attr
->dwValueType
);
1785 TRACE("returning %d (%08x)\n", ret
, GetLastError());
1789 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType
,
1790 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1791 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1794 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
1795 CRYPT_AsnDecodeUnicodeRdnAttr
, sizeof(CERT_RDN_ATTR
), TRUE
,
1796 offsetof(CERT_RDN_ATTR
, pszObjId
) };
1797 PCERT_RDN rdn
= (PCERT_RDN
)pvStructInfo
;
1799 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1800 pDecodePara
, pvStructInfo
, pcbStructInfo
, rdn
? rdn
->rgRDNAttr
: NULL
);
1804 static BOOL WINAPI
CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType
,
1805 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1806 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1812 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
1813 CRYPT_AsnDecodeUnicodeRdn
, sizeof(CERT_RDN
), TRUE
,
1814 offsetof(CERT_RDN
, rgRDNAttr
) };
1816 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1817 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
1821 SetLastError(STATUS_ACCESS_VIOLATION
);
1828 static BOOL WINAPI
CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType
,
1829 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1830 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1833 DWORD bytesNeeded
= sizeof(CRYPT_OBJID_BLOB
);
1835 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1836 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1838 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
1839 bytesNeeded
+= cbEncoded
;
1841 *pcbStructInfo
= bytesNeeded
;
1842 else if (*pcbStructInfo
< bytesNeeded
)
1844 SetLastError(ERROR_MORE_DATA
);
1845 *pcbStructInfo
= bytesNeeded
;
1850 PCRYPT_OBJID_BLOB blob
= (PCRYPT_OBJID_BLOB
)pvStructInfo
;
1852 *pcbStructInfo
= bytesNeeded
;
1853 blob
->cbData
= cbEncoded
;
1854 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
1855 blob
->pbData
= (LPBYTE
)pbEncoded
;
1858 assert(blob
->pbData
);
1859 memcpy(blob
->pbData
, pbEncoded
, blob
->cbData
);
1865 static BOOL WINAPI
CRYPT_DecodeDERArray(DWORD dwCertEncodingType
,
1866 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1867 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1870 struct AsnArrayDescriptor arrayDesc
= { 0, CRYPT_AsnDecodeCopyBytes
,
1871 sizeof(CRYPT_DER_BLOB
), TRUE
, offsetof(CRYPT_DER_BLOB
, pbData
) };
1872 struct GenericArray
*array
= (struct GenericArray
*)pvStructInfo
;
1874 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1875 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1877 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1878 pDecodePara
, pvStructInfo
, pcbStructInfo
, array
? array
->rgItems
: NULL
);
1882 static BOOL WINAPI
CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType
,
1883 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1884 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1890 struct AsnDecodeSequenceItem items
[] = {
1891 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ATTRIBUTE
, pszObjId
),
1892 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1893 offsetof(CRYPT_ATTRIBUTE
, pszObjId
), 0 },
1894 { ASN_CONSTRUCTOR
| ASN_SETOF
, offsetof(CRYPT_ATTRIBUTE
, cValue
),
1895 CRYPT_DecodeDERArray
, sizeof(struct GenericArray
), FALSE
, TRUE
,
1896 offsetof(CRYPT_ATTRIBUTE
, rgValue
), 0 },
1898 PCRYPT_ATTRIBUTE attr
= (PCRYPT_ATTRIBUTE
)pvStructInfo
;
1900 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1901 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
1902 pDecodePara
, pvStructInfo
, pcbStructInfo
, attr
? attr
->pszObjId
:
1907 SetLastError(STATUS_ACCESS_VIOLATION
);
1910 TRACE("returning %d\n", ret
);
1914 static BOOL WINAPI
CRYPT_AsnDecodePKCSAttributesInternal(
1915 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
1916 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
1917 void *pvStructInfo
, DWORD
*pcbStructInfo
)
1919 struct AsnArrayDescriptor arrayDesc
= { 0, CRYPT_AsnDecodePKCSAttribute
,
1920 sizeof(CRYPT_ATTRIBUTE
), TRUE
, offsetof(CRYPT_ATTRIBUTE
, pszObjId
) };
1921 PCRYPT_ATTRIBUTES attrs
= (PCRYPT_ATTRIBUTES
)pvStructInfo
;
1924 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
1925 pDecodePara
, pvStructInfo
, pcbStructInfo
, attrs
? attrs
->rgAttr
:
1930 static BOOL WINAPI
CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType
,
1931 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1932 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1936 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1937 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1944 SetLastError(CRYPT_E_ASN1_EOD
);
1945 else if (pbEncoded
[0] != (ASN_CONSTRUCTOR
| ASN_SETOF
))
1946 SetLastError(CRYPT_E_ASN1_CORRUPT
);
1947 else if ((ret
= CRYPT_AsnDecodePKCSAttributesInternal(
1948 dwCertEncodingType
, lpszStructType
, pbEncoded
, cbEncoded
,
1949 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
1952 *pcbStructInfo
= bytesNeeded
;
1953 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
1954 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
1956 PCRYPT_ATTRIBUTES attrs
;
1958 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
1959 pvStructInfo
= *(BYTE
**)pvStructInfo
;
1960 attrs
= (PCRYPT_ATTRIBUTES
)pvStructInfo
;
1961 attrs
->rgAttr
= (PCRYPT_ATTRIBUTE
)((BYTE
*)pvStructInfo
+
1962 sizeof(CRYPT_ATTRIBUTES
));
1963 ret
= CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType
,
1964 lpszStructType
, pbEncoded
, cbEncoded
,
1965 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
1972 SetLastError(STATUS_ACCESS_VIOLATION
);
1975 TRACE("returning %d\n", ret
);
1979 static BOOL WINAPI
CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType
,
1980 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
1981 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
1983 CRYPT_ALGORITHM_IDENTIFIER
*algo
=
1984 (CRYPT_ALGORITHM_IDENTIFIER
*)pvStructInfo
;
1986 struct AsnDecodeSequenceItem items
[] = {
1987 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
),
1988 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
1989 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, pszObjId
), 0 },
1990 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
),
1991 CRYPT_AsnDecodeCopyBytes
, sizeof(CRYPT_OBJID_BLOB
), TRUE
, TRUE
,
1992 offsetof(CRYPT_ALGORITHM_IDENTIFIER
, Parameters
.pbData
), 0 },
1995 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
1996 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
1998 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
1999 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2000 pDecodePara
, pvStructInfo
, pcbStructInfo
, algo
? algo
->pszObjId
: NULL
);
2001 if (ret
&& pvStructInfo
)
2003 TRACE("pszObjId is %p (%s)\n", algo
->pszObjId
,
2004 debugstr_a(algo
->pszObjId
));
2009 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType
,
2010 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2011 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2014 struct AsnDecodeSequenceItem items
[] = {
2015 { ASN_SEQUENCEOF
, offsetof(CERT_PUBLIC_KEY_INFO
, Algorithm
),
2016 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2017 FALSE
, TRUE
, offsetof(CERT_PUBLIC_KEY_INFO
,
2018 Algorithm
.pszObjId
) },
2019 { ASN_BITSTRING
, offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
),
2020 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
2021 offsetof(CERT_PUBLIC_KEY_INFO
, PublicKey
.pbData
) },
2023 PCERT_PUBLIC_KEY_INFO info
= (PCERT_PUBLIC_KEY_INFO
)pvStructInfo
;
2025 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2026 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2027 pDecodePara
, pvStructInfo
, pcbStructInfo
, info
?
2028 info
->Algorithm
.Parameters
.pbData
: NULL
);
2032 static BOOL WINAPI
CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType
,
2033 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2034 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2042 if ((ret
= CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType
,
2043 lpszStructType
, pbEncoded
, cbEncoded
,
2044 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
2047 *pcbStructInfo
= bytesNeeded
;
2048 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2049 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2051 PCERT_PUBLIC_KEY_INFO info
;
2053 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2054 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2055 info
= (PCERT_PUBLIC_KEY_INFO
)pvStructInfo
;
2056 info
->Algorithm
.Parameters
.pbData
= (BYTE
*)pvStructInfo
+
2057 sizeof(CERT_PUBLIC_KEY_INFO
);
2058 ret
= CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType
,
2059 lpszStructType
, pbEncoded
, cbEncoded
,
2060 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
2067 SetLastError(STATUS_ACCESS_VIOLATION
);
2074 static BOOL WINAPI
CRYPT_AsnDecodeBool(DWORD dwCertEncodingType
,
2075 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2076 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2082 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2085 if (GET_LEN_BYTES(pbEncoded
[1]) > 1)
2087 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2090 if (pbEncoded
[1] > 1)
2092 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2097 *pcbStructInfo
= sizeof(BOOL
);
2100 else if (*pcbStructInfo
< sizeof(BOOL
))
2102 *pcbStructInfo
= sizeof(BOOL
);
2103 SetLastError(ERROR_MORE_DATA
);
2108 *(BOOL
*)pvStructInfo
= pbEncoded
[2] ? TRUE
: FALSE
;
2111 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2115 static BOOL WINAPI
CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType
,
2116 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2117 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2119 PCERT_ALT_NAME_ENTRY entry
= (PCERT_ALT_NAME_ENTRY
)pvStructInfo
;
2120 DWORD dataLen
, lenBytes
, bytesNeeded
= sizeof(CERT_ALT_NAME_ENTRY
);
2123 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2124 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2128 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2131 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2132 if (1 + lenBytes
> cbEncoded
)
2134 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2137 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2139 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
2141 case 1: /* rfc822Name */
2142 case 2: /* dNSName */
2143 case 6: /* uniformResourceIdentifier */
2144 bytesNeeded
+= (dataLen
+ 1) * sizeof(WCHAR
);
2146 case 4: /* directoryName */
2147 case 7: /* iPAddress */
2148 bytesNeeded
+= dataLen
;
2150 case 8: /* registeredID */
2151 ret
= CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType
, NULL
,
2152 pbEncoded
, cbEncoded
, 0, NULL
, NULL
, &dataLen
);
2155 /* FIXME: ugly, shouldn't need to know internals of OID decode
2156 * function to use it.
2158 bytesNeeded
+= dataLen
- sizeof(LPSTR
);
2161 case 0: /* otherName */
2162 FIXME("%d: stub\n", pbEncoded
[0] & ASN_TYPE_MASK
);
2163 SetLastError(CRYPT_E_ASN1_BADTAG
);
2166 case 3: /* x400Address, unimplemented */
2167 case 5: /* ediPartyName, unimplemented */
2168 TRACE("type %d unimplemented\n", pbEncoded
[0] & ASN_TYPE_MASK
);
2169 SetLastError(CRYPT_E_ASN1_BADTAG
);
2173 TRACE("type %d bad\n", pbEncoded
[0] & ASN_TYPE_MASK
);
2174 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2180 *pcbStructInfo
= bytesNeeded
;
2181 else if (*pcbStructInfo
< bytesNeeded
)
2183 *pcbStructInfo
= bytesNeeded
;
2184 SetLastError(ERROR_MORE_DATA
);
2189 *pcbStructInfo
= bytesNeeded
;
2190 /* MS used values one greater than the asn1 ones.. sigh */
2191 entry
->dwAltNameChoice
= (pbEncoded
[0] & 0x7f) + 1;
2192 switch (pbEncoded
[0] & ASN_TYPE_MASK
)
2194 case 1: /* rfc822Name */
2195 case 2: /* dNSName */
2196 case 6: /* uniformResourceIdentifier */
2200 for (i
= 0; i
< dataLen
; i
++)
2201 entry
->u
.pwszURL
[i
] =
2202 (WCHAR
)pbEncoded
[1 + lenBytes
+ i
];
2203 entry
->u
.pwszURL
[i
] = 0;
2204 TRACE("URL is %p (%s)\n", entry
->u
.pwszURL
,
2205 debugstr_w(entry
->u
.pwszURL
));
2208 case 4: /* directoryName */
2209 entry
->dwAltNameChoice
= CERT_ALT_NAME_DIRECTORY_NAME
;
2210 /* The data are memory-equivalent with the IPAddress case,
2213 case 7: /* iPAddress */
2214 /* The next data pointer is in the pwszURL spot, that is,
2215 * the first 4 bytes. Need to move it to the next spot.
2217 entry
->u
.IPAddress
.pbData
= (LPBYTE
)entry
->u
.pwszURL
;
2218 entry
->u
.IPAddress
.cbData
= dataLen
;
2219 memcpy(entry
->u
.IPAddress
.pbData
, pbEncoded
+ 1 + lenBytes
,
2222 case 8: /* registeredID */
2223 ret
= CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType
, NULL
,
2224 pbEncoded
, cbEncoded
, 0, NULL
, &entry
->u
.pszRegisteredID
,
2234 static BOOL WINAPI
CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType
,
2235 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2236 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2239 struct AsnArrayDescriptor arrayDesc
= { 0,
2240 CRYPT_AsnDecodeAltNameEntry
, sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
2241 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
2242 PCERT_ALT_NAME_INFO info
= (PCERT_ALT_NAME_INFO
)pvStructInfo
;
2244 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2245 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2248 TRACE("info->rgAltEntry is %p\n", info
->rgAltEntry
);
2249 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2250 pDecodePara
, pvStructInfo
, pcbStructInfo
, info
? info
->rgAltEntry
: NULL
);
2254 static BOOL WINAPI
CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType
,
2255 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2256 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2262 struct AsnDecodeSequenceItem items
[] = {
2263 { ASN_CONTEXT
| 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO
, KeyId
),
2264 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_DATA_BLOB
),
2265 TRUE
, TRUE
, offsetof(CERT_AUTHORITY_KEY_ID_INFO
, KeyId
.pbData
), 0 },
2266 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1,
2267 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertIssuer
),
2268 CRYPT_AsnDecodeOctetsInternal
, sizeof(CERT_NAME_BLOB
), TRUE
, TRUE
,
2269 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertIssuer
.pbData
), 0 },
2270 { ASN_CONTEXT
| 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO
,
2271 CertSerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2272 sizeof(CRYPT_INTEGER_BLOB
), TRUE
, TRUE
,
2273 offsetof(CERT_AUTHORITY_KEY_ID_INFO
, CertSerialNumber
.pbData
), 0 },
2276 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2277 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2278 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2282 SetLastError(STATUS_ACCESS_VIOLATION
);
2289 static BOOL WINAPI
CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType
,
2290 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2291 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2297 struct AsnDecodeSequenceItem items
[] = {
2298 { ASN_CONTEXT
| 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, KeyId
),
2299 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_DATA_BLOB
),
2300 TRUE
, TRUE
, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, KeyId
.pbData
), 0 },
2301 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 1,
2302 offsetof(CERT_AUTHORITY_KEY_ID2_INFO
, AuthorityCertIssuer
),
2303 CRYPT_AsnDecodeAltNameInternal
, sizeof(CERT_ALT_NAME_INFO
), TRUE
,
2304 TRUE
, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2305 AuthorityCertIssuer
.rgAltEntry
), 0 },
2306 { ASN_CONTEXT
| 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2307 AuthorityCertSerialNumber
), CRYPT_AsnDecodeIntegerInternal
,
2308 sizeof(CRYPT_INTEGER_BLOB
), TRUE
, TRUE
,
2309 offsetof(CERT_AUTHORITY_KEY_ID2_INFO
,
2310 AuthorityCertSerialNumber
.pbData
), 0 },
2313 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2314 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2315 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2319 SetLastError(STATUS_ACCESS_VIOLATION
);
2326 static BOOL WINAPI
CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType
,
2327 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2328 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2333 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2334 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2336 /* The caller has already checked the tag, no need to check it again.
2337 * Check the outer length is valid by calling CRYPT_GetLen:
2339 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2341 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2344 pbEncoded
+= 1 + lenBytes
;
2345 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2346 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &innerLen
)))
2348 ret
= CRYPT_AsnDecodeCopyBytes(dwCertEncodingType
, NULL
,
2349 pbEncoded
, dataLen
, dwFlags
, pDecodePara
, pvStructInfo
,
2356 static BOOL WINAPI
CRYPT_AsnDecodePKCSContentInfoInternal(
2357 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
2358 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2359 void *pvStructInfo
, DWORD
*pcbStructInfo
)
2361 CRYPT_CONTENT_INFO
*info
= (CRYPT_CONTENT_INFO
*)pvStructInfo
;
2362 struct AsnDecodeSequenceItem items
[] = {
2363 { ASN_OBJECTIDENTIFIER
, offsetof(CRYPT_CONTENT_INFO
, pszObjId
),
2364 CRYPT_AsnDecodeOidIgnoreTag
, sizeof(LPSTR
), FALSE
, TRUE
,
2365 offsetof(CRYPT_CONTENT_INFO
, pszObjId
), 0 },
2366 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0,
2367 offsetof(CRYPT_CONTENT_INFO
, Content
), CRYPT_AsnDecodePKCSContent
,
2368 sizeof(CRYPT_DER_BLOB
), TRUE
, TRUE
,
2369 offsetof(CRYPT_CONTENT_INFO
, Content
.pbData
), 0 },
2373 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2374 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2376 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2377 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2378 pDecodePara
, pvStructInfo
, pcbStructInfo
, info
? info
->pszObjId
: NULL
);
2382 static BOOL WINAPI
CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType
,
2383 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2384 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2388 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2389 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2393 ret
= CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType
,
2394 lpszStructType
, pbEncoded
, cbEncoded
,
2395 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
2396 if (ret
&& pvStructInfo
)
2398 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
2399 pcbStructInfo
, *pcbStructInfo
);
2402 CRYPT_CONTENT_INFO
*info
;
2404 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2405 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2406 info
= (CRYPT_CONTENT_INFO
*)pvStructInfo
;
2407 info
->pszObjId
= (LPSTR
)((BYTE
*)info
+
2408 sizeof(CRYPT_CONTENT_INFO
));
2409 ret
= CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType
,
2410 lpszStructType
, pbEncoded
, cbEncoded
,
2411 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
2418 SetLastError(STATUS_ACCESS_VIOLATION
);
2424 BOOL
CRYPT_AsnDecodePKCSDigestedData(const BYTE
*pbEncoded
, DWORD cbEncoded
,
2425 DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
2426 CRYPT_DIGESTED_DATA
*digestedData
, DWORD
*pcbDigestedData
)
2429 struct AsnDecodeSequenceItem items
[] = {
2430 { ASN_INTEGER
, offsetof(CRYPT_DIGESTED_DATA
, version
), CRYPT_AsnDecodeInt
,
2431 sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
2432 { ASN_SEQUENCEOF
, offsetof(CRYPT_DIGESTED_DATA
, DigestAlgorithm
),
2433 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
2434 FALSE
, TRUE
, offsetof(CRYPT_DIGESTED_DATA
, DigestAlgorithm
.pszObjId
),
2436 { ASN_SEQUENCEOF
, offsetof(CRYPT_DIGESTED_DATA
, ContentInfo
),
2437 CRYPT_AsnDecodePKCSContentInfoInternal
,
2438 sizeof(CRYPT_CONTENT_INFO
), FALSE
, TRUE
, offsetof(CRYPT_DIGESTED_DATA
,
2439 ContentInfo
.pszObjId
), 0 },
2440 { ASN_OCTETSTRING
, offsetof(CRYPT_DIGESTED_DATA
, hash
),
2441 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_HASH_BLOB
), FALSE
, TRUE
,
2442 offsetof(CRYPT_DIGESTED_DATA
, hash
.pbData
), 0 },
2445 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
2446 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2447 pDecodePara
, digestedData
, pcbDigestedData
, NULL
);
2451 static BOOL WINAPI
CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType
,
2452 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2453 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2457 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2458 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2462 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
2463 CRYPT_AsnDecodeAltNameEntry
, sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
2464 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
2466 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2467 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2471 SetLastError(STATUS_ACCESS_VIOLATION
);
2478 struct PATH_LEN_CONSTRAINT
2480 BOOL fPathLenConstraint
;
2481 DWORD dwPathLenConstraint
;
2484 static BOOL WINAPI
CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType
,
2485 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2486 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2490 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2491 pvStructInfo
, *pcbStructInfo
);
2495 if (pbEncoded
[0] == ASN_INTEGER
)
2497 DWORD bytesNeeded
= sizeof(struct PATH_LEN_CONSTRAINT
);
2500 *pcbStructInfo
= bytesNeeded
;
2501 else if (*pcbStructInfo
< bytesNeeded
)
2503 SetLastError(ERROR_MORE_DATA
);
2504 *pcbStructInfo
= bytesNeeded
;
2509 struct PATH_LEN_CONSTRAINT
*constraint
=
2510 (struct PATH_LEN_CONSTRAINT
*)pvStructInfo
;
2511 DWORD size
= sizeof(constraint
->dwPathLenConstraint
);
2513 ret
= CRYPT_AsnDecodeInt(dwCertEncodingType
, X509_INTEGER
,
2514 pbEncoded
, cbEncoded
, 0, NULL
,
2515 &constraint
->dwPathLenConstraint
, &size
);
2517 constraint
->fPathLenConstraint
= TRUE
;
2518 TRACE("got an int, dwPathLenConstraint is %d\n",
2519 constraint
->dwPathLenConstraint
);
2524 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2528 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2532 static BOOL WINAPI
CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType
,
2533 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2534 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2537 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
2538 CRYPT_AsnDecodeCopyBytes
, sizeof(CERT_NAME_BLOB
), TRUE
,
2539 offsetof(CERT_NAME_BLOB
, pbData
) };
2540 struct GenericArray
*entries
= (struct GenericArray
*)pvStructInfo
;
2542 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2543 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2545 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
2546 pDecodePara
, pvStructInfo
, pcbStructInfo
,
2547 entries
? entries
->rgItems
: NULL
);
2548 TRACE("Returning %d (%08x)\n", ret
, GetLastError());
2552 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType
,
2553 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2554 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2560 struct AsnDecodeSequenceItem items
[] = {
2561 { ASN_BITSTRING
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
),
2562 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), FALSE
, TRUE
,
2563 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, SubjectType
.pbData
), 0 },
2564 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
2565 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
2566 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
2567 { ASN_SEQUENCEOF
, offsetof(CERT_BASIC_CONSTRAINTS_INFO
,
2568 cSubtreesConstraint
), CRYPT_AsnDecodeSubtreeConstraints
,
2569 sizeof(struct GenericArray
), TRUE
, TRUE
,
2570 offsetof(CERT_BASIC_CONSTRAINTS_INFO
, rgSubtreesConstraint
), 0 },
2573 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2574 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2575 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2579 SetLastError(STATUS_ACCESS_VIOLATION
);
2586 static BOOL WINAPI
CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType
,
2587 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2588 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2594 struct AsnDecodeSequenceItem items
[] = {
2595 { ASN_BOOL
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
, fCA
),
2596 CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
, FALSE
, 0, 0 },
2597 { ASN_INTEGER
, offsetof(CERT_BASIC_CONSTRAINTS2_INFO
,
2598 fPathLenConstraint
), CRYPT_AsnDecodePathLenConstraint
,
2599 sizeof(struct PATH_LEN_CONSTRAINT
), TRUE
, FALSE
, 0, 0 },
2602 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2603 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
2604 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
2608 SetLastError(STATUS_ACCESS_VIOLATION
);
2615 #define RSA1_MAGIC 0x31415352
2617 struct DECODED_RSA_PUB_KEY
2620 CRYPT_INTEGER_BLOB modulus
;
2623 static BOOL WINAPI
CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType
,
2624 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2625 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2631 struct AsnDecodeSequenceItem items
[] = {
2632 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
),
2633 CRYPT_AsnDecodeUnsignedIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
),
2634 FALSE
, TRUE
, offsetof(struct DECODED_RSA_PUB_KEY
, modulus
.pbData
),
2636 { ASN_INTEGER
, offsetof(struct DECODED_RSA_PUB_KEY
, pubexp
),
2637 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
2639 struct DECODED_RSA_PUB_KEY
*decodedKey
= NULL
;
2642 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
2643 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
2644 CRYPT_DECODE_ALLOC_FLAG
, NULL
, &decodedKey
, &size
, NULL
);
2647 DWORD bytesNeeded
= sizeof(BLOBHEADER
) + sizeof(RSAPUBKEY
) +
2648 decodedKey
->modulus
.cbData
;
2652 *pcbStructInfo
= bytesNeeded
;
2655 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2656 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2659 RSAPUBKEY
*rsaPubKey
;
2661 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2662 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2663 hdr
= (BLOBHEADER
*)pvStructInfo
;
2664 hdr
->bType
= PUBLICKEYBLOB
;
2665 hdr
->bVersion
= CUR_BLOB_VERSION
;
2667 hdr
->aiKeyAlg
= CALG_RSA_KEYX
;
2668 rsaPubKey
= (RSAPUBKEY
*)((BYTE
*)pvStructInfo
+
2669 sizeof(BLOBHEADER
));
2670 rsaPubKey
->magic
= RSA1_MAGIC
;
2671 rsaPubKey
->pubexp
= decodedKey
->pubexp
;
2672 rsaPubKey
->bitlen
= decodedKey
->modulus
.cbData
* 8;
2673 memcpy((BYTE
*)pvStructInfo
+ sizeof(BLOBHEADER
) +
2674 sizeof(RSAPUBKEY
), decodedKey
->modulus
.pbData
,
2675 decodedKey
->modulus
.cbData
);
2677 LocalFree(decodedKey
);
2682 SetLastError(STATUS_ACCESS_VIOLATION
);
2689 static BOOL WINAPI
CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType
,
2690 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2691 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2694 DWORD bytesNeeded
, dataLen
;
2696 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2697 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2699 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2701 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2702 bytesNeeded
= sizeof(CRYPT_DATA_BLOB
);
2704 bytesNeeded
= dataLen
+ sizeof(CRYPT_DATA_BLOB
);
2706 *pcbStructInfo
= bytesNeeded
;
2707 else if (*pcbStructInfo
< bytesNeeded
)
2709 SetLastError(ERROR_MORE_DATA
);
2710 *pcbStructInfo
= bytesNeeded
;
2715 CRYPT_DATA_BLOB
*blob
;
2716 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2718 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2719 blob
->cbData
= dataLen
;
2720 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2721 blob
->pbData
= (BYTE
*)pbEncoded
+ 1 + lenBytes
;
2724 assert(blob
->pbData
);
2726 memcpy(blob
->pbData
, pbEncoded
+ 1 + lenBytes
,
2734 static BOOL WINAPI
CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType
,
2735 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2736 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2740 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
2741 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2749 SetLastError(CRYPT_E_ASN1_CORRUPT
);
2752 else if (pbEncoded
[0] != ASN_OCTETSTRING
)
2754 SetLastError(CRYPT_E_ASN1_BADTAG
);
2757 else if ((ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
2758 lpszStructType
, pbEncoded
, cbEncoded
,
2759 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
2762 *pcbStructInfo
= bytesNeeded
;
2763 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2764 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2766 CRYPT_DATA_BLOB
*blob
;
2768 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2769 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2770 blob
= (CRYPT_DATA_BLOB
*)pvStructInfo
;
2771 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_DATA_BLOB
);
2772 ret
= CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType
,
2773 lpszStructType
, pbEncoded
, cbEncoded
,
2774 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
2781 SetLastError(STATUS_ACCESS_VIOLATION
);
2788 static BOOL WINAPI
CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType
,
2789 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2790 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2794 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded
, cbEncoded
, dwFlags
,
2795 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
2797 if (pbEncoded
[0] == ASN_BITSTRING
)
2799 DWORD bytesNeeded
, dataLen
;
2801 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2803 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2804 bytesNeeded
= sizeof(CRYPT_BIT_BLOB
);
2806 bytesNeeded
= dataLen
- 1 + sizeof(CRYPT_BIT_BLOB
);
2808 *pcbStructInfo
= bytesNeeded
;
2809 else if (*pcbStructInfo
< bytesNeeded
)
2811 *pcbStructInfo
= bytesNeeded
;
2812 SetLastError(ERROR_MORE_DATA
);
2817 CRYPT_BIT_BLOB
*blob
;
2819 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2820 blob
->cbData
= dataLen
- 1;
2821 blob
->cUnusedBits
= *(pbEncoded
+ 1 +
2822 GET_LEN_BYTES(pbEncoded
[1]));
2823 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
2825 blob
->pbData
= (BYTE
*)pbEncoded
+ 2 +
2826 GET_LEN_BYTES(pbEncoded
[1]);
2830 assert(blob
->pbData
);
2833 BYTE mask
= 0xff << blob
->cUnusedBits
;
2835 memcpy(blob
->pbData
, pbEncoded
+ 2 +
2836 GET_LEN_BYTES(pbEncoded
[1]), blob
->cbData
);
2837 blob
->pbData
[blob
->cbData
- 1] &= mask
;
2845 SetLastError(CRYPT_E_ASN1_BADTAG
);
2848 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2852 static BOOL WINAPI
CRYPT_AsnDecodeBits(DWORD dwCertEncodingType
,
2853 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2854 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2858 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded
, cbEncoded
, dwFlags
,
2859 pDecodePara
, pvStructInfo
, pcbStructInfo
);
2865 if ((ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
2866 lpszStructType
, pbEncoded
, cbEncoded
,
2867 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
2870 *pcbStructInfo
= bytesNeeded
;
2871 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2872 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
2874 CRYPT_BIT_BLOB
*blob
;
2876 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2877 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2878 blob
= (CRYPT_BIT_BLOB
*)pvStructInfo
;
2879 blob
->pbData
= (BYTE
*)pvStructInfo
+ sizeof(CRYPT_BIT_BLOB
);
2880 ret
= CRYPT_AsnDecodeBitsInternal(dwCertEncodingType
,
2881 lpszStructType
, pbEncoded
, cbEncoded
,
2882 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
2889 SetLastError(STATUS_ACCESS_VIOLATION
);
2893 TRACE("returning %d (%08x)\n", ret
, GetLastError());
2897 static BOOL WINAPI
CRYPT_AsnDecodeInt(DWORD dwCertEncodingType
,
2898 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2899 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2905 *pcbStructInfo
= sizeof(int);
2910 BYTE buf
[sizeof(CRYPT_INTEGER_BLOB
) + sizeof(int)];
2911 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)buf
;
2912 DWORD size
= sizeof(buf
);
2914 blob
->pbData
= buf
+ sizeof(CRYPT_INTEGER_BLOB
);
2915 if (pbEncoded
[0] != ASN_INTEGER
)
2917 SetLastError(CRYPT_E_ASN1_BADTAG
);
2921 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
2922 X509_MULTI_BYTE_INTEGER
, pbEncoded
, cbEncoded
, 0, NULL
, &buf
,
2926 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
2927 pvStructInfo
, pcbStructInfo
, sizeof(int))))
2931 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
2932 pvStructInfo
= *(BYTE
**)pvStructInfo
;
2933 if (blob
->pbData
[blob
->cbData
- 1] & 0x80)
2935 /* initialize to a negative value to sign-extend */
2940 for (i
= 0; i
< blob
->cbData
; i
++)
2943 val
|= blob
->pbData
[blob
->cbData
- i
- 1];
2945 memcpy(pvStructInfo
, &val
, sizeof(int));
2948 else if (GetLastError() == ERROR_MORE_DATA
)
2949 SetLastError(CRYPT_E_ASN1_LARGE
);
2953 SetLastError(STATUS_ACCESS_VIOLATION
);
2960 static BOOL WINAPI
CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType
,
2961 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
2962 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
2965 DWORD bytesNeeded
, dataLen
;
2967 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
2969 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
2971 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
2973 *pcbStructInfo
= bytesNeeded
;
2974 else if (*pcbStructInfo
< bytesNeeded
)
2976 *pcbStructInfo
= bytesNeeded
;
2977 SetLastError(ERROR_MORE_DATA
);
2982 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
2984 blob
->cbData
= dataLen
;
2985 assert(blob
->pbData
);
2990 for (i
= 0; i
< blob
->cbData
; i
++)
2992 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
3001 static BOOL WINAPI
CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType
,
3002 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3003 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3011 if (pbEncoded
[0] != ASN_INTEGER
)
3013 SetLastError(CRYPT_E_ASN1_BADTAG
);
3017 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
3018 lpszStructType
, pbEncoded
, cbEncoded
,
3019 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
);
3023 *pcbStructInfo
= bytesNeeded
;
3024 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3025 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3027 CRYPT_INTEGER_BLOB
*blob
;
3029 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3030 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3031 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3032 blob
->pbData
= (BYTE
*)pvStructInfo
+
3033 sizeof(CRYPT_INTEGER_BLOB
);
3034 ret
= CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType
,
3035 lpszStructType
, pbEncoded
, cbEncoded
,
3036 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3043 SetLastError(STATUS_ACCESS_VIOLATION
);
3050 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedIntegerInternal(
3051 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
3052 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
3053 void *pvStructInfo
, DWORD
*pcbStructInfo
)
3057 if (pbEncoded
[0] == ASN_INTEGER
)
3059 DWORD bytesNeeded
, dataLen
;
3061 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3063 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3065 bytesNeeded
= dataLen
+ sizeof(CRYPT_INTEGER_BLOB
);
3067 *pcbStructInfo
= bytesNeeded
;
3068 else if (*pcbStructInfo
< bytesNeeded
)
3070 *pcbStructInfo
= bytesNeeded
;
3071 SetLastError(ERROR_MORE_DATA
);
3076 CRYPT_INTEGER_BLOB
*blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3078 blob
->cbData
= dataLen
;
3079 assert(blob
->pbData
);
3080 /* remove leading zero byte if it exists */
3081 if (blob
->cbData
&& *(pbEncoded
+ 1 + lenBytes
) == 0)
3090 for (i
= 0; i
< blob
->cbData
; i
++)
3092 blob
->pbData
[i
] = *(pbEncoded
+ 1 + lenBytes
+
3101 SetLastError(CRYPT_E_ASN1_BADTAG
);
3107 static BOOL WINAPI
CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType
,
3108 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3109 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3117 if ((ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
3118 lpszStructType
, pbEncoded
, cbEncoded
,
3119 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, NULL
, &bytesNeeded
)))
3122 *pcbStructInfo
= bytesNeeded
;
3123 else if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3124 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3126 CRYPT_INTEGER_BLOB
*blob
;
3128 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3129 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3130 blob
= (CRYPT_INTEGER_BLOB
*)pvStructInfo
;
3131 blob
->pbData
= (BYTE
*)pvStructInfo
+
3132 sizeof(CRYPT_INTEGER_BLOB
);
3133 ret
= CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType
,
3134 lpszStructType
, pbEncoded
, cbEncoded
,
3135 dwFlags
& ~CRYPT_ENCODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3142 SetLastError(STATUS_ACCESS_VIOLATION
);
3149 static BOOL WINAPI
CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType
,
3150 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3151 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3157 *pcbStructInfo
= sizeof(int);
3162 if (pbEncoded
[0] == ASN_ENUMERATED
)
3164 unsigned int val
= 0, i
;
3168 SetLastError(CRYPT_E_ASN1_EOD
);
3171 else if (pbEncoded
[1] == 0)
3173 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3178 /* A little strange looking, but we have to accept a sign byte:
3179 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3180 * assuming a small length is okay here, it has to be in short
3183 if (pbEncoded
[1] > sizeof(unsigned int) + 1)
3185 SetLastError(CRYPT_E_ASN1_LARGE
);
3188 for (i
= 0; i
< pbEncoded
[1]; i
++)
3191 val
|= pbEncoded
[2 + i
];
3193 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3194 pvStructInfo
, pcbStructInfo
, sizeof(unsigned int))))
3196 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3197 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3198 memcpy(pvStructInfo
, &val
, sizeof(unsigned int));
3204 SetLastError(CRYPT_E_ASN1_BADTAG
);
3210 SetLastError(STATUS_ACCESS_VIOLATION
);
3217 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3220 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3225 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3227 if (!isdigit(*(pbEncoded))) \
3229 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3235 (word) += *(pbEncoded)++ - '0'; \
3240 static BOOL
CRYPT_AsnDecodeTimeZone(const BYTE
*pbEncoded
, DWORD len
,
3241 SYSTEMTIME
*sysTime
)
3248 if (len
>= 3 && (*pbEncoded
== '+' || *pbEncoded
== '-'))
3250 WORD hours
, minutes
= 0;
3251 BYTE sign
= *pbEncoded
++;
3254 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, hours
);
3255 if (ret
&& hours
>= 24)
3257 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3262 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, minutes
);
3263 if (ret
&& minutes
>= 60)
3265 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3273 sysTime
->wHour
+= hours
;
3274 sysTime
->wMinute
+= minutes
;
3278 if (hours
> sysTime
->wHour
)
3281 sysTime
->wHour
= 24 - (hours
- sysTime
->wHour
);
3284 sysTime
->wHour
-= hours
;
3285 if (minutes
> sysTime
->wMinute
)
3288 sysTime
->wMinute
= 60 - (minutes
- sysTime
->wMinute
);
3291 sysTime
->wMinute
-= minutes
;
3298 SetLastError(STATUS_ACCESS_VIOLATION
);
3305 #define MIN_ENCODED_TIME_LENGTH 10
3307 static BOOL WINAPI
CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType
,
3308 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3309 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3315 *pcbStructInfo
= sizeof(FILETIME
);
3321 if (pbEncoded
[0] == ASN_UTCTIME
)
3325 SetLastError(CRYPT_E_ASN1_EOD
);
3328 else if (pbEncoded
[1] > 0x7f)
3330 /* long-form date strings really can't be valid */
3331 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3336 SYSTEMTIME sysTime
= { 0 };
3337 BYTE len
= pbEncoded
[1];
3339 if (len
< MIN_ENCODED_TIME_LENGTH
)
3341 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3347 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wYear
);
3348 if (sysTime
.wYear
>= 50)
3349 sysTime
.wYear
+= 1900;
3351 sysTime
.wYear
+= 2000;
3352 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
3353 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
3354 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
3355 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMinute
);
3358 if (len
>= 2 && isdigit(*pbEncoded
) &&
3359 isdigit(*(pbEncoded
+ 1)))
3360 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3362 else if (isdigit(*pbEncoded
))
3363 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 1,
3366 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
3369 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3370 pDecodePara
, pvStructInfo
, pcbStructInfo
,
3373 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3374 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3375 ret
= SystemTimeToFileTime(&sysTime
,
3376 (FILETIME
*)pvStructInfo
);
3383 SetLastError(CRYPT_E_ASN1_BADTAG
);
3389 SetLastError(STATUS_ACCESS_VIOLATION
);
3396 static BOOL WINAPI
CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType
,
3397 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3398 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3404 *pcbStructInfo
= sizeof(FILETIME
);
3410 if (pbEncoded
[0] == ASN_GENERALTIME
)
3414 SetLastError(CRYPT_E_ASN1_EOD
);
3417 else if (pbEncoded
[1] > 0x7f)
3419 /* long-form date strings really can't be valid */
3420 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3425 BYTE len
= pbEncoded
[1];
3427 if (len
< MIN_ENCODED_TIME_LENGTH
)
3429 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3434 SYSTEMTIME sysTime
= { 0 };
3437 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 4, sysTime
.wYear
);
3438 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wMonth
);
3439 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wDay
);
3440 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2, sysTime
.wHour
);
3443 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3446 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, 2,
3448 if (ret
&& len
> 0 && (*pbEncoded
== '.' ||
3455 /* workaround macro weirdness */
3456 digits
= min(len
, 3);
3457 CRYPT_TIME_GET_DIGITS(pbEncoded
, len
, digits
,
3458 sysTime
.wMilliseconds
);
3461 ret
= CRYPT_AsnDecodeTimeZone(pbEncoded
, len
,
3464 if (ret
&& (ret
= CRYPT_DecodeEnsureSpace(dwFlags
,
3465 pDecodePara
, pvStructInfo
, pcbStructInfo
,
3468 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3469 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3470 ret
= SystemTimeToFileTime(&sysTime
,
3471 (FILETIME
*)pvStructInfo
);
3478 SetLastError(CRYPT_E_ASN1_BADTAG
);
3484 SetLastError(STATUS_ACCESS_VIOLATION
);
3491 static BOOL WINAPI
CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType
,
3492 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3493 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3499 if (pbEncoded
[0] == ASN_UTCTIME
)
3500 ret
= CRYPT_AsnDecodeUtcTime(dwCertEncodingType
, lpszStructType
,
3501 pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
,
3503 else if (pbEncoded
[0] == ASN_GENERALTIME
)
3504 ret
= CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType
,
3505 lpszStructType
, pbEncoded
, cbEncoded
, dwFlags
, pDecodePara
,
3506 pvStructInfo
, pcbStructInfo
);
3509 SetLastError(CRYPT_E_ASN1_BADTAG
);
3515 SetLastError(STATUS_ACCESS_VIOLATION
);
3522 static BOOL WINAPI
CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType
,
3523 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3524 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3530 if (pbEncoded
[0] == ASN_SEQUENCEOF
)
3532 DWORD bytesNeeded
, dataLen
, remainingLen
, cValue
;
3534 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3539 lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3540 bytesNeeded
= sizeof(CRYPT_SEQUENCE_OF_ANY
);
3542 ptr
= pbEncoded
+ 1 + lenBytes
;
3543 remainingLen
= dataLen
;
3544 while (ret
&& remainingLen
)
3548 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
3551 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
3553 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
3554 ptr
+= 1 + nextLenBytes
+ nextLen
;
3555 bytesNeeded
+= sizeof(CRYPT_DER_BLOB
);
3556 if (!(dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
))
3557 bytesNeeded
+= 1 + nextLenBytes
+ nextLen
;
3563 CRYPT_SEQUENCE_OF_ANY
*seq
;
3567 if ((ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
,
3568 pvStructInfo
, pcbStructInfo
, bytesNeeded
)))
3570 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3571 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3572 seq
= (CRYPT_SEQUENCE_OF_ANY
*)pvStructInfo
;
3573 seq
->cValue
= cValue
;
3574 seq
->rgValue
= (CRYPT_DER_BLOB
*)((BYTE
*)seq
+
3576 nextPtr
= (BYTE
*)seq
->rgValue
+
3577 cValue
* sizeof(CRYPT_DER_BLOB
);
3578 ptr
= pbEncoded
+ 1 + lenBytes
;
3579 remainingLen
= dataLen
;
3581 while (ret
&& remainingLen
)
3585 ret
= CRYPT_GetLen(ptr
, remainingLen
, &nextLen
);
3588 DWORD nextLenBytes
= GET_LEN_BYTES(ptr
[1]);
3590 seq
->rgValue
[i
].cbData
= 1 + nextLenBytes
+
3592 if (dwFlags
& CRYPT_DECODE_NOCOPY_FLAG
)
3593 seq
->rgValue
[i
].pbData
= (BYTE
*)ptr
;
3596 seq
->rgValue
[i
].pbData
= nextPtr
;
3597 memcpy(nextPtr
, ptr
, 1 + nextLenBytes
+
3599 nextPtr
+= 1 + nextLenBytes
+ nextLen
;
3601 remainingLen
-= 1 + nextLenBytes
+ nextLen
;
3602 ptr
+= 1 + nextLenBytes
+ nextLen
;
3612 SetLastError(CRYPT_E_ASN1_BADTAG
);
3618 SetLastError(STATUS_ACCESS_VIOLATION
);
3625 static BOOL WINAPI
CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType
,
3626 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3627 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3631 if (pbEncoded
[0] == (ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0))
3633 DWORD bytesNeeded
, dataLen
;
3635 if ((ret
= CRYPT_GetLen(pbEncoded
, cbEncoded
, &dataLen
)))
3637 struct AsnArrayDescriptor arrayDesc
= {
3638 ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, CRYPT_AsnDecodeAltNameEntry
,
3639 sizeof(CERT_ALT_NAME_ENTRY
), TRUE
,
3640 offsetof(CERT_ALT_NAME_ENTRY
, u
.pwszURL
) };
3641 BYTE lenBytes
= GET_LEN_BYTES(pbEncoded
[1]);
3647 ret
= CRYPT_AsnDecodeArray(&arrayDesc
,
3648 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
3649 0, NULL
, NULL
, &nameLen
, NULL
);
3650 bytesNeeded
= sizeof(CRL_DIST_POINT_NAME
) + nameLen
;
3653 bytesNeeded
= sizeof(CRL_DIST_POINT_NAME
);
3655 *pcbStructInfo
= bytesNeeded
;
3656 else if (*pcbStructInfo
< bytesNeeded
)
3658 *pcbStructInfo
= bytesNeeded
;
3659 SetLastError(ERROR_MORE_DATA
);
3664 CRL_DIST_POINT_NAME
*name
= (CRL_DIST_POINT_NAME
*)pvStructInfo
;
3668 name
->dwDistPointNameChoice
= CRL_DIST_POINT_FULL_NAME
;
3669 ret
= CRYPT_AsnDecodeArray(&arrayDesc
,
3670 pbEncoded
+ 1 + lenBytes
, cbEncoded
- 1 - lenBytes
,
3671 0, NULL
, &name
->u
.FullName
, pcbStructInfo
,
3672 name
->u
.FullName
.rgAltEntry
);
3675 name
->dwDistPointNameChoice
= CRL_DIST_POINT_NO_NAME
;
3681 SetLastError(CRYPT_E_ASN1_BADTAG
);
3687 static BOOL WINAPI
CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType
,
3688 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3689 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3691 struct AsnDecodeSequenceItem items
[] = {
3692 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_DIST_POINT
,
3693 DistPointName
), CRYPT_AsnDecodeDistPointName
,
3694 sizeof(CRL_DIST_POINT_NAME
), TRUE
, TRUE
, offsetof(CRL_DIST_POINT
,
3695 DistPointName
.u
.FullName
.rgAltEntry
), 0 },
3696 { ASN_CONTEXT
| 1, offsetof(CRL_DIST_POINT
, ReasonFlags
),
3697 CRYPT_AsnDecodeBitsInternal
, sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
,
3698 offsetof(CRL_DIST_POINT
, ReasonFlags
.pbData
), 0 },
3699 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 2, offsetof(CRL_DIST_POINT
, CRLIssuer
),
3700 CRYPT_AsnDecodeAltNameInternal
, sizeof(CERT_ALT_NAME_INFO
), TRUE
, TRUE
,
3701 offsetof(CRL_DIST_POINT
, CRLIssuer
.rgAltEntry
), 0 },
3705 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3706 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
3707 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3711 static BOOL WINAPI
CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType
,
3712 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3713 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3717 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3718 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3722 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3723 CRYPT_AsnDecodeDistPoint
, sizeof(CRL_DIST_POINT
), TRUE
,
3724 offsetof(CRL_DIST_POINT
, DistPointName
.u
.FullName
.rgAltEntry
) };
3726 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3727 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3731 SetLastError(STATUS_ACCESS_VIOLATION
);
3738 static BOOL WINAPI
CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType
,
3739 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3740 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3744 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3745 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3749 struct AsnArrayDescriptor arrayDesc
= { ASN_SEQUENCEOF
,
3750 CRYPT_AsnDecodeOidInternal
, sizeof(LPSTR
), TRUE
, 0 };
3752 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3753 pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3757 SetLastError(STATUS_ACCESS_VIOLATION
);
3764 static BOOL WINAPI
CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType
,
3765 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3766 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3770 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3771 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3775 struct AsnDecodeSequenceItem items
[] = {
3776 { ASN_CONTEXT
| ASN_CONSTRUCTOR
| 0, offsetof(CRL_ISSUING_DIST_POINT
,
3777 DistPointName
), CRYPT_AsnDecodeDistPointName
,
3778 sizeof(CRL_DIST_POINT_NAME
), TRUE
, TRUE
,
3779 offsetof(CRL_ISSUING_DIST_POINT
,
3780 DistPointName
.u
.FullName
.rgAltEntry
), 0 },
3781 { ASN_CONTEXT
| 1, offsetof(CRL_ISSUING_DIST_POINT
,
3782 fOnlyContainsUserCerts
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
,
3784 { ASN_CONTEXT
| 2, offsetof(CRL_ISSUING_DIST_POINT
,
3785 fOnlyContainsCACerts
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
,
3787 { ASN_CONTEXT
| 3, offsetof(CRL_ISSUING_DIST_POINT
,
3788 OnlySomeReasonFlags
), CRYPT_AsnDecodeBitsInternal
,
3789 sizeof(CRYPT_BIT_BLOB
), TRUE
, TRUE
, offsetof(CRL_ISSUING_DIST_POINT
,
3790 OnlySomeReasonFlags
.pbData
), 0 },
3791 { ASN_CONTEXT
| 4, offsetof(CRL_ISSUING_DIST_POINT
,
3792 fIndirectCRL
), CRYPT_AsnDecodeBool
, sizeof(BOOL
), TRUE
, FALSE
, 0 },
3795 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3796 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
3797 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
, NULL
);
3801 SetLastError(STATUS_ACCESS_VIOLATION
);
3808 static BOOL WINAPI
CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType
,
3809 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3810 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3813 struct AsnDecodeSequenceItem items
[] = {
3814 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER
, Issuer
), CRYPT_AsnDecodeDerBlob
,
3815 sizeof(CRYPT_DER_BLOB
), FALSE
, TRUE
, offsetof(CERT_ISSUER_SERIAL_NUMBER
,
3817 { ASN_INTEGER
, offsetof(CERT_ISSUER_SERIAL_NUMBER
, SerialNumber
),
3818 CRYPT_AsnDecodeIntegerInternal
, sizeof(CRYPT_INTEGER_BLOB
), FALSE
,
3819 TRUE
, offsetof(CERT_ISSUER_SERIAL_NUMBER
, SerialNumber
.pbData
), 0 },
3821 CERT_ISSUER_SERIAL_NUMBER
*issuerSerial
=
3822 (CERT_ISSUER_SERIAL_NUMBER
*)pvStructInfo
;
3824 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3825 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3827 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3828 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
3829 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
,
3830 issuerSerial
? issuerSerial
->Issuer
.pbData
: NULL
);
3831 if (ret
&& issuerSerial
&& !issuerSerial
->SerialNumber
.cbData
)
3833 SetLastError(CRYPT_E_ASN1_CORRUPT
);
3836 TRACE("returning %d\n", ret
);
3840 static BOOL WINAPI
CRYPT_AsnDecodePKCSSignerInfoInternal(
3841 DWORD dwCertEncodingType
, LPCSTR lpszStructType
, const BYTE
*pbEncoded
,
3842 DWORD cbEncoded
, DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
3843 void *pvStructInfo
, DWORD
*pcbStructInfo
)
3845 CMSG_SIGNER_INFO
*info
= (CMSG_SIGNER_INFO
*)pvStructInfo
;
3846 struct AsnDecodeSequenceItem items
[] = {
3847 { ASN_INTEGER
, offsetof(CMSG_SIGNER_INFO
, dwVersion
),
3848 CRYPT_AsnDecodeInt
, sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
3849 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, Issuer
),
3850 CRYPT_AsnDecodeIssuerSerialNumber
, sizeof(CERT_ISSUER_SERIAL_NUMBER
),
3851 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, Issuer
.pbData
), 0 },
3852 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, HashAlgorithm
),
3853 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3854 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, HashAlgorithm
.pszObjId
), 0 },
3855 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0,
3856 offsetof(CMSG_SIGNER_INFO
, AuthAttrs
),
3857 CRYPT_AsnDecodePKCSAttributesInternal
, sizeof(CRYPT_ATTRIBUTES
),
3858 TRUE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, AuthAttrs
.rgAttr
), 0 },
3859 { ASN_SEQUENCEOF
, offsetof(CMSG_SIGNER_INFO
, HashEncryptionAlgorithm
),
3860 CRYPT_AsnDecodeAlgorithmId
, sizeof(CRYPT_ALGORITHM_IDENTIFIER
),
3861 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
,
3862 HashEncryptionAlgorithm
.pszObjId
), 0 },
3863 { ASN_OCTETSTRING
, offsetof(CMSG_SIGNER_INFO
, EncryptedHash
),
3864 CRYPT_AsnDecodeOctetsInternal
, sizeof(CRYPT_DER_BLOB
),
3865 FALSE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, EncryptedHash
.pbData
), 0 },
3866 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
3867 offsetof(CMSG_SIGNER_INFO
, UnauthAttrs
),
3868 CRYPT_AsnDecodePKCSAttributesInternal
, sizeof(CRYPT_ATTRIBUTES
),
3869 TRUE
, TRUE
, offsetof(CMSG_SIGNER_INFO
, UnauthAttrs
.rgAttr
), 0 },
3873 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3874 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3876 ret
= CRYPT_AsnDecodeSequence(dwCertEncodingType
, items
,
3877 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
,
3878 dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
,
3879 info
? info
->Issuer
.pbData
: NULL
);
3883 static BOOL WINAPI
CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType
,
3884 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3885 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3889 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3890 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3894 ret
= CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType
,
3895 lpszStructType
, pbEncoded
, cbEncoded
,
3896 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, NULL
, pcbStructInfo
);
3897 if (ret
&& pvStructInfo
)
3899 ret
= CRYPT_DecodeEnsureSpace(dwFlags
, pDecodePara
, pvStructInfo
,
3900 pcbStructInfo
, *pcbStructInfo
);
3903 CMSG_SIGNER_INFO
*info
;
3905 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
)
3906 pvStructInfo
= *(BYTE
**)pvStructInfo
;
3907 info
= (CMSG_SIGNER_INFO
*)pvStructInfo
;
3908 info
->Issuer
.pbData
= ((BYTE
*)info
+
3909 sizeof(CMSG_SIGNER_INFO
));
3910 ret
= CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType
,
3911 lpszStructType
, pbEncoded
, cbEncoded
,
3912 dwFlags
& ~CRYPT_DECODE_ALLOC_FLAG
, NULL
, pvStructInfo
,
3919 SetLastError(STATUS_ACCESS_VIOLATION
);
3922 TRACE("returning %d\n", ret
);
3926 static BOOL WINAPI
CRYPT_DecodeSignerArray(DWORD dwCertEncodingType
,
3927 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3928 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3931 struct AsnArrayDescriptor arrayDesc
= { ASN_CONSTRUCTOR
| ASN_SETOF
,
3932 CRYPT_AsnDecodePKCSSignerInfoInternal
, sizeof(CMSG_SIGNER_INFO
), TRUE
,
3933 offsetof(CMSG_SIGNER_INFO
, Issuer
.pbData
) };
3934 struct GenericArray
*array
= (struct GenericArray
*)pvStructInfo
;
3936 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3937 pDecodePara
, pvStructInfo
, *pcbStructInfo
);
3939 ret
= CRYPT_AsnDecodeArray(&arrayDesc
, pbEncoded
, cbEncoded
, dwFlags
,
3940 pDecodePara
, pvStructInfo
, pcbStructInfo
, array
? array
->rgItems
: NULL
);
3944 BOOL
CRYPT_AsnDecodePKCSSignedInfo(const BYTE
*pbEncoded
, DWORD cbEncoded
,
3945 DWORD dwFlags
, PCRYPT_DECODE_PARA pDecodePara
,
3946 CRYPT_SIGNED_INFO
*signedInfo
, DWORD
*pcbSignedInfo
)
3949 struct AsnDecodeSequenceItem items
[] = {
3950 { ASN_INTEGER
, offsetof(CRYPT_SIGNED_INFO
, version
), CRYPT_AsnDecodeInt
,
3951 sizeof(DWORD
), FALSE
, FALSE
, 0, 0 },
3952 /* Placeholder for the hash algorithms - redundant with those in the
3953 * signers, so just ignore them.
3955 { ASN_CONSTRUCTOR
| ASN_SETOF
, 0, NULL
, 0, TRUE
, FALSE
, 0, 0 },
3956 { ASN_SEQUENCE
, offsetof(CRYPT_SIGNED_INFO
, content
),
3957 CRYPT_AsnDecodePKCSContentInfoInternal
, sizeof(CRYPT_CONTENT_INFO
),
3958 FALSE
, TRUE
, offsetof(CRYPT_SIGNED_INFO
, content
.pszObjId
), 0 },
3959 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 0,
3960 offsetof(CRYPT_SIGNED_INFO
, cCertEncoded
),
3961 CRYPT_DecodeDERArray
, sizeof(struct GenericArray
), TRUE
, TRUE
,
3962 offsetof(CRYPT_SIGNED_INFO
, rgCertEncoded
), 0 },
3963 { ASN_CONSTRUCTOR
| ASN_CONTEXT
| 1,
3964 offsetof(CRYPT_SIGNED_INFO
, cCrlEncoded
), CRYPT_DecodeDERArray
,
3965 sizeof(struct GenericArray
), TRUE
, TRUE
,
3966 offsetof(CRYPT_SIGNED_INFO
, rgCrlEncoded
), 0 },
3967 { ASN_CONSTRUCTOR
| ASN_SETOF
, offsetof(CRYPT_SIGNED_INFO
, cSignerInfo
),
3968 CRYPT_DecodeSignerArray
, sizeof(struct GenericArray
), TRUE
, TRUE
,
3969 offsetof(CRYPT_SIGNED_INFO
, rgSignerInfo
), 0 },
3972 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded
, cbEncoded
, dwFlags
,
3973 pDecodePara
, signedInfo
, *pcbSignedInfo
);
3975 ret
= CRYPT_AsnDecodeSequence(X509_ASN_ENCODING
, items
,
3976 sizeof(items
) / sizeof(items
[0]), pbEncoded
, cbEncoded
, dwFlags
,
3977 pDecodePara
, signedInfo
, pcbSignedInfo
, NULL
);
3978 TRACE("returning %d\n", ret
);
3982 BOOL WINAPI
CryptDecodeObjectEx(DWORD dwCertEncodingType
, LPCSTR lpszStructType
,
3983 const BYTE
*pbEncoded
, DWORD cbEncoded
, DWORD dwFlags
,
3984 PCRYPT_DECODE_PARA pDecodePara
, void *pvStructInfo
, DWORD
*pcbStructInfo
)
3986 static HCRYPTOIDFUNCSET set
= NULL
;
3988 CryptDecodeObjectExFunc decodeFunc
= NULL
;
3989 HCRYPTOIDFUNCADDR hFunc
= NULL
;
3991 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
3992 dwCertEncodingType
, debugstr_a(lpszStructType
), pbEncoded
,
3993 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
3995 if (!pvStructInfo
&& !pcbStructInfo
)
3997 SetLastError(ERROR_INVALID_PARAMETER
);
4000 if ((dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
4001 && (dwCertEncodingType
& CMSG_ENCODING_TYPE_MASK
) != PKCS_7_ASN_ENCODING
)
4003 SetLastError(ERROR_FILE_NOT_FOUND
);
4008 SetLastError(CRYPT_E_ASN1_EOD
);
4011 if (cbEncoded
> MAX_ENCODED_LEN
)
4013 SetLastError(CRYPT_E_ASN1_LARGE
);
4017 SetLastError(NOERROR
);
4018 if (dwFlags
& CRYPT_DECODE_ALLOC_FLAG
&& pvStructInfo
)
4019 *(BYTE
**)pvStructInfo
= NULL
;
4020 if (!HIWORD(lpszStructType
))
4022 switch (LOWORD(lpszStructType
))
4024 case (WORD
)X509_CERT
:
4025 decodeFunc
= CRYPT_AsnDecodeCertSignedContent
;
4027 case (WORD
)X509_CERT_TO_BE_SIGNED
:
4028 decodeFunc
= CRYPT_AsnDecodeCert
;
4030 case (WORD
)X509_CERT_CRL_TO_BE_SIGNED
:
4031 decodeFunc
= CRYPT_AsnDecodeCRL
;
4033 case (WORD
)X509_EXTENSIONS
:
4034 decodeFunc
= CRYPT_AsnDecodeExtensions
;
4036 case (WORD
)X509_NAME_VALUE
:
4037 decodeFunc
= CRYPT_AsnDecodeNameValue
;
4039 case (WORD
)X509_NAME
:
4040 decodeFunc
= CRYPT_AsnDecodeName
;
4042 case (WORD
)X509_PUBLIC_KEY_INFO
:
4043 decodeFunc
= CRYPT_AsnDecodePubKeyInfo
;
4045 case (WORD
)X509_AUTHORITY_KEY_ID
:
4046 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId
;
4048 case (WORD
)X509_ALTERNATE_NAME
:
4049 decodeFunc
= CRYPT_AsnDecodeAltName
;
4051 case (WORD
)X509_BASIC_CONSTRAINTS
:
4052 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
4054 case (WORD
)X509_BASIC_CONSTRAINTS2
:
4055 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
4057 case (WORD
)RSA_CSP_PUBLICKEYBLOB
:
4058 decodeFunc
= CRYPT_AsnDecodeRsaPubKey
;
4060 case (WORD
)X509_UNICODE_NAME
:
4061 decodeFunc
= CRYPT_AsnDecodeUnicodeName
;
4063 case (WORD
)PKCS_ATTRIBUTE
:
4064 decodeFunc
= CRYPT_AsnDecodePKCSAttribute
;
4066 case (WORD
)X509_UNICODE_NAME_VALUE
:
4067 decodeFunc
= CRYPT_AsnDecodeUnicodeNameValue
;
4069 case (WORD
)X509_OCTET_STRING
:
4070 decodeFunc
= CRYPT_AsnDecodeOctets
;
4072 case (WORD
)X509_BITS
:
4073 case (WORD
)X509_KEY_USAGE
:
4074 decodeFunc
= CRYPT_AsnDecodeBits
;
4076 case (WORD
)X509_INTEGER
:
4077 decodeFunc
= CRYPT_AsnDecodeInt
;
4079 case (WORD
)X509_MULTI_BYTE_INTEGER
:
4080 decodeFunc
= CRYPT_AsnDecodeInteger
;
4082 case (WORD
)X509_MULTI_BYTE_UINT
:
4083 decodeFunc
= CRYPT_AsnDecodeUnsignedInteger
;
4085 case (WORD
)X509_ENUMERATED
:
4086 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
4088 case (WORD
)X509_CHOICE_OF_TIME
:
4089 decodeFunc
= CRYPT_AsnDecodeChoiceOfTime
;
4091 case (WORD
)X509_AUTHORITY_KEY_ID2
:
4092 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId2
;
4094 case (WORD
)PKCS_CONTENT_INFO
:
4095 decodeFunc
= CRYPT_AsnDecodePKCSContentInfo
;
4097 case (WORD
)X509_SEQUENCE_OF_ANY
:
4098 decodeFunc
= CRYPT_AsnDecodeSequenceOfAny
;
4100 case (WORD
)PKCS_UTC_TIME
:
4101 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
4103 case (WORD
)X509_CRL_DIST_POINTS
:
4104 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
4106 case (WORD
)X509_ENHANCED_KEY_USAGE
:
4107 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
4109 case (WORD
)PKCS_ATTRIBUTES
:
4110 decodeFunc
= CRYPT_AsnDecodePKCSAttributes
;
4112 case (WORD
)X509_ISSUING_DIST_POINT
:
4113 decodeFunc
= CRYPT_AsnDecodeIssuingDistPoint
;
4115 case (WORD
)PKCS7_SIGNER_INFO
:
4116 decodeFunc
= CRYPT_AsnDecodePKCSSignerInfo
;
4119 FIXME("%d: unimplemented\n", LOWORD(lpszStructType
));
4122 else if (!strcmp(lpszStructType
, szOID_CERT_EXTENSIONS
))
4123 decodeFunc
= CRYPT_AsnDecodeExtensions
;
4124 else if (!strcmp(lpszStructType
, szOID_RSA_signingTime
))
4125 decodeFunc
= CRYPT_AsnDecodeUtcTime
;
4126 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER
))
4127 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId
;
4128 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
4129 decodeFunc
= CRYPT_AsnDecodeAuthorityKeyId2
;
4130 else if (!strcmp(lpszStructType
, szOID_CRL_REASON_CODE
))
4131 decodeFunc
= CRYPT_AsnDecodeEnumerated
;
4132 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
4133 decodeFunc
= CRYPT_AsnDecodeBits
;
4134 else if (!strcmp(lpszStructType
, szOID_SUBJECT_KEY_IDENTIFIER
))
4135 decodeFunc
= CRYPT_AsnDecodeOctets
;
4136 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS
))
4137 decodeFunc
= CRYPT_AsnDecodeBasicConstraints
;
4138 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
4139 decodeFunc
= CRYPT_AsnDecodeBasicConstraints2
;
4140 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
4141 decodeFunc
= CRYPT_AsnDecodeAltName
;
4142 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
4143 decodeFunc
= CRYPT_AsnDecodeAltName
;
4144 else if (!strcmp(lpszStructType
, szOID_NEXT_UPDATE_LOCATION
))
4145 decodeFunc
= CRYPT_AsnDecodeAltName
;
4146 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
4147 decodeFunc
= CRYPT_AsnDecodeAltName
;
4148 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
4149 decodeFunc
= CRYPT_AsnDecodeAltName
;
4150 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
4151 decodeFunc
= CRYPT_AsnDecodeCRLDistPoints
;
4152 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
4153 decodeFunc
= CRYPT_AsnDecodeEnhancedKeyUsage
;
4154 else if (!strcmp(lpszStructType
, szOID_ISSUING_DIST_POINT
))
4155 decodeFunc
= CRYPT_AsnDecodeIssuingDistPoint
;
4157 TRACE("OID %s not found or unimplemented, looking for DLL\n",
4158 debugstr_a(lpszStructType
));
4162 set
= CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC
, 0);
4163 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
4164 (void **)&decodeFunc
, &hFunc
);
4167 ret
= decodeFunc(dwCertEncodingType
, lpszStructType
, pbEncoded
,
4168 cbEncoded
, dwFlags
, pDecodePara
, pvStructInfo
, pcbStructInfo
);
4170 SetLastError(ERROR_FILE_NOT_FOUND
);
4172 CryptFreeOIDFunctionAddress(hFunc
, 0);