crypt32: Improve tracing when builtin function isn't available.
[wine.git] / dlls / crypt32 / decode.c
blobf1915d4f7f978d4404fc6eb6a016c0606d853f4f
1 /*
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.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially:
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
34 #include <assert.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
39 #define NONAMELESSUNION
41 #include "windef.h"
42 #include "winbase.h"
43 #include "wincrypt.h"
44 #include "winnls.h"
45 #include "snmp.h"
46 #include "wine/debug.h"
47 #include "wine/exception.h"
48 #include "crypt32_private.h"
50 /* This is a bit arbitrary, but to set some limit: */
51 #define MAX_ENCODED_LEN 0x02000000
53 #define ASN_FLAGS_MASK 0xe0
54 #define ASN_TYPE_MASK 0x1f
56 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
57 WINE_DECLARE_DEBUG_CHANNEL(crypt);
59 struct GenericArray
61 DWORD cItems;
62 BYTE *rgItems;
65 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
66 DWORD, DWORD, void *, DWORD *);
67 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
68 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
70 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
71 * The dwCertEncodingType and lpszStructType are ignored by the built-in
72 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
73 * since it must call functions in external DLLs that follow these signatures.
75 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
77 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
78 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
80 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
81 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
82 * time, doesn't do memory allocation, and doesn't do exception handling.
83 * (This isn't intended to be the externally-called one.)
85 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
86 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
87 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
88 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
89 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
90 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
91 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
92 /* Internal function */
93 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
94 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
95 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
96 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
97 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
98 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
99 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
100 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
101 * member has been initialized, doesn't do exception handling, and doesn't do
102 * memory allocation.
104 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
105 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
106 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
107 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
108 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
109 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
110 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
111 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
112 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
113 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
114 * member has been initialized, doesn't do exception handling, and doesn't do
115 * memory allocation. Also doesn't check tag, assumes the caller has checked
116 * it.
118 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
119 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
120 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
121 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
122 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
123 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
124 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
125 void *pvStructInfo, DWORD *pcbStructInfo);
127 /* Gets the number of length bytes from the given (leading) length byte */
128 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
130 /* Helper function to get the encoded length of the data starting at pbEncoded,
131 * where pbEncoded[0] is the tag. If the data are too short to contain a
132 * length or if the length is too large for cbEncoded, sets an appropriate
133 * error code and returns FALSE.
135 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
136 DWORD *len)
138 BOOL ret;
140 if (cbEncoded <= 1)
142 SetLastError(CRYPT_E_ASN1_CORRUPT);
143 ret = FALSE;
145 else if (pbEncoded[1] <= 0x7f)
147 if (pbEncoded[1] + 1 > cbEncoded)
149 SetLastError(CRYPT_E_ASN1_EOD);
150 ret = FALSE;
152 else
154 *len = pbEncoded[1];
155 ret = TRUE;
158 else if (pbEncoded[1] == 0x80)
160 FIXME("unimplemented for indefinite-length encoding\n");
161 SetLastError(CRYPT_E_ASN1_CORRUPT);
162 ret = FALSE;
164 else
166 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
168 if (lenLen > sizeof(DWORD) + 1)
170 SetLastError(CRYPT_E_ASN1_LARGE);
171 ret = FALSE;
173 else if (lenLen + 2 > cbEncoded)
175 SetLastError(CRYPT_E_ASN1_CORRUPT);
176 ret = FALSE;
178 else
180 DWORD out = 0;
182 pbEncoded += 2;
183 while (--lenLen)
185 out <<= 8;
186 out |= *pbEncoded++;
188 if (out + lenLen + 1 > cbEncoded)
190 SetLastError(CRYPT_E_ASN1_EOD);
191 ret = FALSE;
193 else
195 *len = out;
196 ret = TRUE;
200 return ret;
203 /* Helper function to check *pcbStructInfo, set it to the required size, and
204 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
205 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
206 * pointer to the newly allocated memory.
208 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
209 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
210 DWORD bytesNeeded)
212 BOOL ret = TRUE;
214 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
216 if (pDecodePara && pDecodePara->pfnAlloc)
217 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
218 else
219 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
220 if (!*(BYTE **)pvStructInfo)
221 ret = FALSE;
222 else
223 *pcbStructInfo = bytesNeeded;
225 else if (*pcbStructInfo < bytesNeeded)
227 *pcbStructInfo = bytesNeeded;
228 SetLastError(ERROR_MORE_DATA);
229 ret = FALSE;
231 return ret;
234 /* tag:
235 * The expected tag of the item. If tag is 0, decodeFunc is called
236 * regardless of the tag value seen.
237 * offset:
238 * A sequence is decoded into a struct. The offset member is the
239 * offset of this item within that struct.
240 * decodeFunc:
241 * The decoder function to use. If this is NULL, then the member isn't
242 * decoded, but minSize space is reserved for it.
243 * minSize:
244 * The minimum amount of space occupied after decoding. You must set this.
245 * optional:
246 * If true, and the tag doesn't match the expected tag for this item,
247 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
248 * filled with 0 for this member.
249 * hasPointer, pointerOffset:
250 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
251 * the offset within the struct of the data pointer (or to the
252 * first data pointer, if more than one exist).
253 * size:
254 * Used by CRYPT_AsnDecodeSequence, not for your use.
256 struct AsnDecodeSequenceItem
258 BYTE tag;
259 DWORD offset;
260 CryptDecodeObjectExFunc decodeFunc;
261 DWORD minSize;
262 BOOL optional;
263 BOOL hasPointer;
264 DWORD pointerOffset;
265 DWORD size;
268 /* Decodes the items in a sequence, where the items are described in items,
269 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
270 * pvStructInfo. nextData is a pointer to the memory location at which the
271 * first decoded item with a dynamic pointer should point.
272 * Upon decoding, *cbDecoded is the total number of bytes decoded.
274 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
275 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
276 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
277 DWORD *cbDecoded)
279 BOOL ret;
280 DWORD i, decoded = 0;
281 const BYTE *ptr = pbEncoded;
283 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
284 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
286 for (i = 0, ret = TRUE; ret && i < cItem; i++)
288 if (cbEncoded - (ptr - pbEncoded) != 0)
290 DWORD nextItemLen;
292 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
293 &nextItemLen)))
295 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
297 if (ptr[0] == items[i].tag || !items[i].tag)
299 if (nextData && pvStructInfo && items[i].hasPointer)
301 TRACE("Setting next pointer to %p\n",
302 nextData);
303 *(BYTE **)((BYTE *)pvStructInfo +
304 items[i].pointerOffset) = nextData;
306 if (items[i].decodeFunc)
308 if (pvStructInfo)
309 TRACE("decoding item %d\n", i);
310 else
311 TRACE("sizing item %d\n", i);
312 ret = items[i].decodeFunc(dwCertEncodingType,
313 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
314 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
315 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
316 : NULL, &items[i].size);
317 if (ret)
319 /* Account for alignment padding */
320 if (items[i].size % sizeof(DWORD))
321 items[i].size += sizeof(DWORD) -
322 items[i].size % sizeof(DWORD);
323 TRACE("item %d size: %d\n", i, items[i].size);
324 if (nextData && items[i].hasPointer &&
325 items[i].size > items[i].minSize)
326 nextData += items[i].size - items[i].minSize;
327 ptr += 1 + nextItemLenBytes + nextItemLen;
328 decoded += 1 + nextItemLenBytes + nextItemLen;
329 TRACE("item %d: decoded %d bytes\n", i,
330 1 + nextItemLenBytes + nextItemLen);
332 else if (items[i].optional &&
333 GetLastError() == CRYPT_E_ASN1_BADTAG)
335 TRACE("skipping optional item %d\n", i);
336 items[i].size = items[i].minSize;
337 SetLastError(NOERROR);
338 ret = TRUE;
340 else
341 TRACE("item %d failed: %08x\n", i,
342 GetLastError());
344 else
346 TRACE("item %d: decoded %d bytes\n", i,
347 1 + nextItemLenBytes + nextItemLen);
348 ptr += 1 + nextItemLenBytes + nextItemLen;
349 decoded += 1 + nextItemLenBytes + nextItemLen;
350 items[i].size = items[i].minSize;
353 else if (items[i].optional)
355 TRACE("skipping optional item %d\n", i);
356 items[i].size = items[i].minSize;
358 else
360 TRACE("item %d: tag %02x doesn't match expected %02x\n",
361 i, ptr[0], items[i].tag);
362 SetLastError(CRYPT_E_ASN1_BADTAG);
363 ret = FALSE;
367 else if (items[i].optional)
369 TRACE("missing optional item %d, skipping\n", i);
370 items[i].size = items[i].minSize;
372 else
374 TRACE("not enough bytes for item %d, failing\n", i);
375 SetLastError(CRYPT_E_ASN1_CORRUPT);
376 ret = FALSE;
379 if (ret)
380 *cbDecoded = decoded;
381 TRACE("returning %d\n", ret);
382 return ret;
385 /* This decodes an arbitrary sequence into a contiguous block of memory
386 * (basically, a struct.) Each element being decoded is described by a struct
387 * AsnDecodeSequenceItem, see above.
388 * startingPointer is an optional pointer to the first place where dynamic
389 * data will be stored. If you know the starting offset, you may pass it
390 * here. Otherwise, pass NULL, and one will be inferred from the items.
391 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
393 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
394 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
395 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
396 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
398 BOOL ret;
400 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
401 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
402 startingPointer);
404 if (pbEncoded[0] == ASN_SEQUENCE)
406 DWORD dataLen;
408 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
410 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
411 const BYTE *ptr = pbEncoded + 1 + lenBytes;
413 cbEncoded -= 1 + lenBytes;
414 if (cbEncoded < dataLen)
416 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
417 cbEncoded);
418 SetLastError(CRYPT_E_ASN1_CORRUPT);
419 ret = FALSE;
421 else
422 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
423 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
424 if (ret && cbDecoded != dataLen)
426 TRACE("expected %d decoded, got %d, failing\n", dataLen,
427 cbDecoded);
428 SetLastError(CRYPT_E_ASN1_CORRUPT);
429 ret = FALSE;
431 if (ret)
433 DWORD i, bytesNeeded = 0, structSize = 0;
435 for (i = 0; i < cItem; i++)
437 bytesNeeded += items[i].size;
438 structSize += items[i].minSize;
440 if (!pvStructInfo)
441 *pcbStructInfo = bytesNeeded;
442 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
443 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
445 BYTE *nextData;
447 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
448 pvStructInfo = *(BYTE **)pvStructInfo;
449 if (startingPointer)
450 nextData = (BYTE *)startingPointer;
451 else
452 nextData = (BYTE *)pvStructInfo + structSize;
453 memset(pvStructInfo, 0, structSize);
454 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
455 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
456 &cbDecoded);
461 else
463 SetLastError(CRYPT_E_ASN1_BADTAG);
464 ret = FALSE;
466 TRACE("returning %d (%08x)\n", ret, GetLastError());
467 return ret;
470 /* tag:
471 * The expected tag of the entire encoded array (usually a variant
472 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
473 * regardless of the tag seen.
474 * decodeFunc:
475 * used to decode each item in the array
476 * itemSize:
477 * is the minimum size of each decoded item
478 * hasPointer:
479 * indicates whether each item has a dynamic pointer
480 * pointerOffset:
481 * indicates the offset within itemSize at which the pointer exists
483 struct AsnArrayDescriptor
485 BYTE tag;
486 CryptDecodeObjectExFunc decodeFunc;
487 DWORD itemSize;
488 BOOL hasPointer;
489 DWORD pointerOffset;
492 struct AsnArrayItemSize
494 DWORD encodedLen;
495 DWORD size;
498 /* Decodes an array of like types into a struct GenericArray.
499 * The layout and decoding of the array are described by a struct
500 * AsnArrayDescriptor.
502 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
503 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
504 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
505 void *startingPointer)
507 BOOL ret = TRUE;
509 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
510 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
511 startingPointer);
513 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
515 DWORD dataLen;
517 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
519 DWORD bytesNeeded, cItems = 0;
520 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
521 /* There can be arbitrarily many items, but there is often only one.
523 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
525 bytesNeeded = sizeof(struct GenericArray);
526 if (dataLen)
528 const BYTE *ptr;
530 for (ptr = pbEncoded + 1 + lenBytes; ret &&
531 ptr - pbEncoded - 1 - lenBytes < dataLen; )
533 DWORD itemLenBytes, itemDataLen, size = 0;
535 itemLenBytes = GET_LEN_BYTES(ptr[1]);
536 /* Each item decoded may not tolerate extraneous bytes, so
537 * get the length of the next element and pass it directly.
539 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
540 &itemDataLen);
541 if (ret)
542 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
543 1 + itemLenBytes + itemDataLen,
544 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
545 &size);
546 if (ret)
548 DWORD nextLen;
550 cItems++;
551 if (itemSizes != &itemSize)
552 itemSizes = CryptMemRealloc(itemSizes,
553 cItems * sizeof(struct AsnArrayItemSize));
554 else
556 itemSizes =
557 CryptMemAlloc(
558 cItems * sizeof(struct AsnArrayItemSize));
559 if (itemSizes)
560 memcpy(itemSizes, &itemSize, sizeof(itemSize));
562 if (itemSizes)
564 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
565 + itemDataLen;
566 itemSizes[cItems - 1].size = size;
567 bytesNeeded += size;
568 ret = CRYPT_GetLen(ptr,
569 cbEncoded - (ptr - pbEncoded), &nextLen);
570 if (ret)
571 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
573 else
574 ret = FALSE;
578 if (ret)
580 if (!pvStructInfo)
581 *pcbStructInfo = bytesNeeded;
582 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
583 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
585 DWORD i;
586 BYTE *nextData;
587 const BYTE *ptr;
588 struct GenericArray *array;
590 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
591 pvStructInfo = *(BYTE **)pvStructInfo;
592 array = (struct GenericArray *)pvStructInfo;
593 array->cItems = cItems;
594 if (startingPointer)
595 array->rgItems = startingPointer;
596 else
597 array->rgItems = (BYTE *)array +
598 sizeof(struct GenericArray);
599 nextData = (BYTE *)array->rgItems +
600 array->cItems * arrayDesc->itemSize;
601 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
602 i < cItems && ptr - pbEncoded - 1 - lenBytes <
603 dataLen; i++)
605 if (arrayDesc->hasPointer)
606 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
607 + arrayDesc->pointerOffset) = nextData;
608 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
609 itemSizes[i].encodedLen,
610 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
611 array->rgItems + i * arrayDesc->itemSize,
612 &itemSizes[i].size);
613 if (ret)
615 DWORD nextLen;
617 nextData += itemSizes[i].size - arrayDesc->itemSize;
618 ret = CRYPT_GetLen(ptr,
619 cbEncoded - (ptr - pbEncoded), &nextLen);
620 if (ret)
621 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
626 if (itemSizes != &itemSize)
627 CryptMemFree(itemSizes);
630 else
632 SetLastError(CRYPT_E_ASN1_BADTAG);
633 ret = FALSE;
635 return ret;
638 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
639 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
640 * to CRYPT_E_ASN1_CORRUPT.
641 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
642 * set!
644 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
645 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
646 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
648 BOOL ret;
649 DWORD dataLen;
651 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
653 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
654 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
656 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
657 bytesNeeded += 1 + lenBytes + dataLen;
659 if (!pvStructInfo)
660 *pcbStructInfo = bytesNeeded;
661 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
662 pvStructInfo, pcbStructInfo, bytesNeeded)))
664 CRYPT_DER_BLOB *blob;
666 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
667 pvStructInfo = *(BYTE **)pvStructInfo;
668 blob = (CRYPT_DER_BLOB *)pvStructInfo;
669 blob->cbData = 1 + lenBytes + dataLen;
670 if (blob->cbData)
672 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
673 blob->pbData = (BYTE *)pbEncoded;
674 else
676 assert(blob->pbData);
677 memcpy(blob->pbData, pbEncoded, blob->cbData);
680 else
682 SetLastError(CRYPT_E_ASN1_CORRUPT);
683 ret = FALSE;
687 return ret;
690 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
691 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
692 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
693 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
695 BOOL ret;
697 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
698 pDecodePara, pvStructInfo, *pcbStructInfo);
700 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
701 * place.
703 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
704 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
705 pvStructInfo, pcbStructInfo);
706 if (ret && pvStructInfo)
708 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
710 if (blob->cbData)
712 DWORD i;
713 BYTE temp;
715 for (i = 0; i < blob->cbData / 2; i++)
717 temp = blob->pbData[i];
718 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
719 blob->pbData[blob->cbData - i - 1] = temp;
723 TRACE("returning %d (%08x)\n", ret, GetLastError());
724 return ret;
727 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
728 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
729 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
731 BOOL ret = TRUE;
733 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
734 pDecodePara, pvStructInfo, *pcbStructInfo);
736 __TRY
738 struct AsnDecodeSequenceItem items[] = {
739 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
740 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
741 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
742 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
743 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
744 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
745 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
746 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
747 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
748 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
751 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
752 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
753 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
754 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
755 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
757 __EXCEPT_PAGE_FAULT
759 SetLastError(STATUS_ACCESS_VIOLATION);
760 ret = FALSE;
762 __ENDTRY
764 TRACE("Returning %d (%08x)\n", ret, GetLastError());
765 return ret;
768 /* Internal function */
769 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
770 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
771 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
773 BOOL ret;
774 DWORD dataLen;
776 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
778 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
780 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
781 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
782 pvStructInfo, pcbStructInfo);
784 return ret;
787 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
788 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
789 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
791 BOOL ret;
793 struct AsnDecodeSequenceItem items[] = {
794 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
795 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
796 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
797 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
800 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
801 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
802 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
803 return ret;
806 /* Internal function */
807 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
808 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
809 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
811 BOOL ret;
812 DWORD dataLen;
814 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
816 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
818 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
819 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
820 pDecodePara, pvStructInfo, pcbStructInfo);
822 return ret;
825 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
826 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
827 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
829 BOOL ret = TRUE;
830 struct AsnDecodeSequenceItem items[] = {
831 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
832 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
833 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
834 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
835 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
836 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
837 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
838 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
839 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
840 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
841 Issuer.pbData) },
842 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
843 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
844 FALSE, 0 },
845 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
846 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
847 Subject.pbData) },
848 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
849 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
850 FALSE, TRUE, offsetof(CERT_INFO,
851 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
852 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
853 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
854 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
855 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
856 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
857 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
858 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
859 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
860 offsetof(CERT_INFO, rgExtension), 0 },
863 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
864 pDecodePara, pvStructInfo, *pcbStructInfo);
866 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
867 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
868 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
869 if (ret && pvStructInfo)
871 CERT_INFO *info;
873 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
874 info = *(CERT_INFO **)pvStructInfo;
875 else
876 info = (CERT_INFO *)pvStructInfo;
877 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
878 !info->Subject.cbData)
880 SetLastError(CRYPT_E_ASN1_CORRUPT);
881 /* Don't need to deallocate, because it should have failed on the
882 * first pass (and no memory was allocated.)
884 ret = FALSE;
888 TRACE("Returning %d (%08x)\n", ret, GetLastError());
889 return ret;
892 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
893 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
894 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
896 BOOL ret = TRUE;
898 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
899 pDecodePara, pvStructInfo, *pcbStructInfo);
901 __TRY
903 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
904 DWORD size = 0;
906 /* First try to decode it as a signed cert. */
907 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
908 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
909 (BYTE *)&signedCert, &size);
910 if (ret)
912 size = 0;
913 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
914 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
915 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
916 pcbStructInfo);
917 LocalFree(signedCert);
919 /* Failing that, try it as an unsigned cert */
920 if (!ret)
922 size = 0;
923 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
924 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
925 pDecodePara, pvStructInfo, pcbStructInfo);
928 __EXCEPT_PAGE_FAULT
930 SetLastError(STATUS_ACCESS_VIOLATION);
931 ret = FALSE;
933 __ENDTRY
935 TRACE("Returning %d (%08x)\n", ret, GetLastError());
936 return ret;
939 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
940 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
941 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
943 BOOL ret;
944 struct AsnDecodeSequenceItem items[] = {
945 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
946 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
947 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
948 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
949 sizeof(FILETIME), FALSE, FALSE, 0 },
950 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
951 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
952 offsetof(CRL_ENTRY, rgExtension), 0 },
954 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
956 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
957 *pcbStructInfo);
959 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
960 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
961 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
962 return ret;
965 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
966 * been set prior to calling.
968 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
969 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
970 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
972 BOOL ret;
973 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
974 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
975 offsetof(CRL_ENTRY, SerialNumber.pbData) };
976 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
978 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
979 pDecodePara, pvStructInfo, *pcbStructInfo);
981 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
982 pDecodePara, pvStructInfo, pcbStructInfo,
983 entries ? entries->rgItems : NULL);
984 TRACE("Returning %d (%08x)\n", ret, GetLastError());
985 return ret;
988 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
989 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
990 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
992 struct AsnDecodeSequenceItem items[] = {
993 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
994 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
995 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
996 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
997 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
998 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
999 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1000 Issuer.pbData) },
1001 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
1002 sizeof(FILETIME), FALSE, FALSE, 0 },
1003 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
1004 sizeof(FILETIME), TRUE, FALSE, 0 },
1005 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1006 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1007 offsetof(CRL_INFO, rgCRLEntry), 0 },
1008 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1009 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1010 offsetof(CRL_INFO, rgExtension), 0 },
1012 BOOL ret = TRUE;
1014 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1015 pDecodePara, pvStructInfo, *pcbStructInfo);
1017 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1018 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1019 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1021 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1022 return ret;
1025 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1026 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1027 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1029 BOOL ret = TRUE;
1031 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1032 pDecodePara, pvStructInfo, *pcbStructInfo);
1034 __TRY
1036 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1037 DWORD size = 0;
1039 /* First try to decode it as a signed crl. */
1040 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1041 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1042 (BYTE *)&signedCrl, &size);
1043 if (ret)
1045 size = 0;
1046 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1047 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1048 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1049 pvStructInfo, pcbStructInfo);
1050 LocalFree(signedCrl);
1052 /* Failing that, try it as an unsigned crl */
1053 if (!ret)
1055 size = 0;
1056 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1057 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1058 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1061 __EXCEPT_PAGE_FAULT
1063 SetLastError(STATUS_ACCESS_VIOLATION);
1064 ret = FALSE;
1066 __ENDTRY
1068 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1069 return ret;
1072 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType,
1073 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1074 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1076 BOOL ret = TRUE;
1077 DWORD dataLen;
1079 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1080 pDecodePara, pvStructInfo, *pcbStructInfo);
1082 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1084 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1085 DWORD bytesNeeded = sizeof(LPSTR);
1087 if (dataLen)
1089 /* The largest possible string for the first two components
1090 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1092 char firstTwo[6];
1093 const BYTE *ptr;
1095 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1096 pbEncoded[1 + lenBytes] / 40,
1097 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1098 * 40);
1099 bytesNeeded += strlen(firstTwo) + 1;
1100 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1101 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1103 /* large enough for ".4000000" */
1104 char str[9];
1105 int val = 0;
1107 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1108 (*ptr & 0x80))
1110 val <<= 7;
1111 val |= *ptr & 0x7f;
1112 ptr++;
1114 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1115 (*ptr & 0x80))
1117 SetLastError(CRYPT_E_ASN1_CORRUPT);
1118 ret = FALSE;
1120 else
1122 val <<= 7;
1123 val |= *ptr++;
1124 snprintf(str, sizeof(str), ".%d", val);
1125 bytesNeeded += strlen(str);
1129 if (!pvStructInfo)
1130 *pcbStructInfo = bytesNeeded;
1131 else if (*pcbStructInfo < bytesNeeded)
1133 *pcbStructInfo = bytesNeeded;
1134 SetLastError(ERROR_MORE_DATA);
1135 ret = FALSE;
1137 else
1139 if (dataLen)
1141 const BYTE *ptr;
1142 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1144 *pszObjId = 0;
1145 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1146 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1147 40) * 40);
1148 pszObjId += strlen(pszObjId);
1149 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1150 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1152 int val = 0;
1154 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1155 (*ptr & 0x80))
1157 val <<= 7;
1158 val |= *ptr & 0x7f;
1159 ptr++;
1161 val <<= 7;
1162 val |= *ptr++;
1163 sprintf(pszObjId, ".%d", val);
1164 pszObjId += strlen(pszObjId);
1167 else
1168 *(LPSTR *)pvStructInfo = NULL;
1169 *pcbStructInfo = bytesNeeded;
1172 return ret;
1175 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1176 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1177 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1179 BOOL ret;
1181 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1182 pDecodePara, pvStructInfo, *pcbStructInfo);
1184 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1185 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, lpszStructType,
1186 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
1187 pcbStructInfo);
1188 else
1190 SetLastError(CRYPT_E_ASN1_BADTAG);
1191 ret = FALSE;
1193 return ret;
1196 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1197 * ahead of time!
1199 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1200 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1201 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1203 struct AsnDecodeSequenceItem items[] = {
1204 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1205 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1206 offsetof(CERT_EXTENSION, pszObjId), 0 },
1207 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1208 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1209 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1210 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1211 offsetof(CERT_EXTENSION, Value.pbData) },
1213 BOOL ret = TRUE;
1214 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1216 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1217 *pcbStructInfo);
1219 if (ext)
1220 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1221 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1222 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1223 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1224 if (ext)
1225 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1226 debugstr_a(ext->pszObjId));
1227 TRACE("returning %d (%08x)\n", ret, GetLastError());
1228 return ret;
1231 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1232 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1233 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1235 BOOL ret = TRUE;
1236 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1237 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1238 offsetof(CERT_EXTENSION, pszObjId) };
1239 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1241 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1242 pDecodePara, pvStructInfo, *pcbStructInfo);
1244 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1245 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1246 return ret;
1249 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1250 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1251 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1253 BOOL ret = TRUE;
1255 __TRY
1257 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1258 lpszStructType, pbEncoded, cbEncoded,
1259 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1260 if (ret && pvStructInfo)
1262 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1263 pcbStructInfo, *pcbStructInfo);
1264 if (ret)
1266 CERT_EXTENSIONS *exts;
1268 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1269 pvStructInfo = *(BYTE **)pvStructInfo;
1270 exts = (CERT_EXTENSIONS *)pvStructInfo;
1271 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1272 sizeof(CERT_EXTENSIONS));
1273 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1274 lpszStructType, pbEncoded, cbEncoded,
1275 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1276 pcbStructInfo);
1280 __EXCEPT_PAGE_FAULT
1282 SetLastError(STATUS_ACCESS_VIOLATION);
1283 ret = FALSE;
1285 __ENDTRY
1286 return ret;
1289 /* Warning: this assumes the address of value->Value.pbData is already set, in
1290 * order to avoid overwriting memory. (In some cases, it may change it, if it
1291 * doesn't copy anything to memory.) Be sure to set it correctly!
1293 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1294 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1295 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1297 BOOL ret = TRUE;
1298 DWORD dataLen;
1299 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1301 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1303 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1304 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1306 switch (pbEncoded[0])
1308 case ASN_OCTETSTRING:
1309 valueType = CERT_RDN_OCTET_STRING;
1310 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1311 bytesNeeded += dataLen;
1312 break;
1313 case ASN_NUMERICSTRING:
1314 valueType = CERT_RDN_NUMERIC_STRING;
1315 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1316 bytesNeeded += dataLen;
1317 break;
1318 case ASN_PRINTABLESTRING:
1319 valueType = CERT_RDN_PRINTABLE_STRING;
1320 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1321 bytesNeeded += dataLen;
1322 break;
1323 case ASN_IA5STRING:
1324 valueType = CERT_RDN_IA5_STRING;
1325 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1326 bytesNeeded += dataLen;
1327 break;
1328 case ASN_T61STRING:
1329 valueType = CERT_RDN_T61_STRING;
1330 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1331 bytesNeeded += dataLen;
1332 break;
1333 case ASN_VIDEOTEXSTRING:
1334 valueType = CERT_RDN_VIDEOTEX_STRING;
1335 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1336 bytesNeeded += dataLen;
1337 break;
1338 case ASN_GRAPHICSTRING:
1339 valueType = CERT_RDN_GRAPHIC_STRING;
1340 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1341 bytesNeeded += dataLen;
1342 break;
1343 case ASN_VISIBLESTRING:
1344 valueType = CERT_RDN_VISIBLE_STRING;
1345 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1346 bytesNeeded += dataLen;
1347 break;
1348 case ASN_GENERALSTRING:
1349 valueType = CERT_RDN_GENERAL_STRING;
1350 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1351 bytesNeeded += dataLen;
1352 break;
1353 case ASN_UNIVERSALSTRING:
1354 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1355 SetLastError(CRYPT_E_ASN1_BADTAG);
1356 return FALSE;
1357 case ASN_BMPSTRING:
1358 valueType = CERT_RDN_BMP_STRING;
1359 bytesNeeded += dataLen;
1360 break;
1361 case ASN_UTF8STRING:
1362 valueType = CERT_RDN_UTF8_STRING;
1363 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1364 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1365 break;
1366 default:
1367 SetLastError(CRYPT_E_ASN1_BADTAG);
1368 return FALSE;
1371 if (!value)
1372 *pcbStructInfo = bytesNeeded;
1373 else if (*pcbStructInfo < bytesNeeded)
1375 *pcbStructInfo = bytesNeeded;
1376 SetLastError(ERROR_MORE_DATA);
1377 ret = FALSE;
1379 else
1381 *pcbStructInfo = bytesNeeded;
1382 value->dwValueType = valueType;
1383 if (dataLen)
1385 DWORD i;
1387 assert(value->Value.pbData);
1388 switch (pbEncoded[0])
1390 case ASN_OCTETSTRING:
1391 case ASN_NUMERICSTRING:
1392 case ASN_PRINTABLESTRING:
1393 case ASN_IA5STRING:
1394 case ASN_T61STRING:
1395 case ASN_VIDEOTEXSTRING:
1396 case ASN_GRAPHICSTRING:
1397 case ASN_VISIBLESTRING:
1398 case ASN_GENERALSTRING:
1399 value->Value.cbData = dataLen;
1400 if (dataLen)
1402 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1403 memcpy(value->Value.pbData,
1404 pbEncoded + 1 + lenBytes, dataLen);
1405 else
1406 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1407 lenBytes;
1409 break;
1410 case ASN_BMPSTRING:
1412 LPWSTR str = (LPWSTR)value->Value.pbData;
1414 value->Value.cbData = dataLen;
1415 for (i = 0; i < dataLen / 2; i++)
1416 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1417 pbEncoded[1 + lenBytes + 2 * i + 1];
1418 break;
1420 case ASN_UTF8STRING:
1422 LPWSTR str = (LPWSTR)value->Value.pbData;
1424 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1425 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1426 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1427 break;
1431 else
1433 value->Value.cbData = 0;
1434 value->Value.pbData = NULL;
1438 return ret;
1441 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1442 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1443 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1445 BOOL ret = TRUE;
1447 __TRY
1449 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1450 lpszStructType, pbEncoded, cbEncoded,
1451 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1452 if (ret && pvStructInfo)
1454 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1455 pcbStructInfo, *pcbStructInfo);
1456 if (ret)
1458 CERT_NAME_VALUE *value;
1460 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1461 pvStructInfo = *(BYTE **)pvStructInfo;
1462 value = (CERT_NAME_VALUE *)pvStructInfo;
1463 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1464 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1465 lpszStructType, pbEncoded, cbEncoded,
1466 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1467 pcbStructInfo);
1471 __EXCEPT_PAGE_FAULT
1473 SetLastError(STATUS_ACCESS_VIOLATION);
1474 ret = FALSE;
1476 __ENDTRY
1477 return ret;
1480 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1481 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1482 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1483 void *pvStructInfo, DWORD *pcbStructInfo)
1485 BOOL ret = TRUE;
1486 DWORD dataLen;
1487 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1489 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1491 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1492 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1494 switch (pbEncoded[0])
1496 case ASN_NUMERICSTRING:
1497 valueType = CERT_RDN_NUMERIC_STRING;
1498 bytesNeeded += dataLen * 2;
1499 break;
1500 case ASN_PRINTABLESTRING:
1501 valueType = CERT_RDN_PRINTABLE_STRING;
1502 bytesNeeded += dataLen * 2;
1503 break;
1504 case ASN_IA5STRING:
1505 valueType = CERT_RDN_IA5_STRING;
1506 bytesNeeded += dataLen * 2;
1507 break;
1508 case ASN_T61STRING:
1509 valueType = CERT_RDN_T61_STRING;
1510 bytesNeeded += dataLen * 2;
1511 break;
1512 case ASN_VIDEOTEXSTRING:
1513 valueType = CERT_RDN_VIDEOTEX_STRING;
1514 bytesNeeded += dataLen * 2;
1515 break;
1516 case ASN_GRAPHICSTRING:
1517 valueType = CERT_RDN_GRAPHIC_STRING;
1518 bytesNeeded += dataLen * 2;
1519 break;
1520 case ASN_VISIBLESTRING:
1521 valueType = CERT_RDN_VISIBLE_STRING;
1522 bytesNeeded += dataLen * 2;
1523 break;
1524 case ASN_GENERALSTRING:
1525 valueType = CERT_RDN_GENERAL_STRING;
1526 bytesNeeded += dataLen * 2;
1527 break;
1528 case ASN_UNIVERSALSTRING:
1529 valueType = CERT_RDN_UNIVERSAL_STRING;
1530 bytesNeeded += dataLen / 2;
1531 break;
1532 case ASN_BMPSTRING:
1533 valueType = CERT_RDN_BMP_STRING;
1534 bytesNeeded += dataLen;
1535 break;
1536 case ASN_UTF8STRING:
1537 valueType = CERT_RDN_UTF8_STRING;
1538 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1539 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1540 break;
1541 default:
1542 SetLastError(CRYPT_E_ASN1_BADTAG);
1543 return FALSE;
1546 if (!value)
1547 *pcbStructInfo = bytesNeeded;
1548 else if (*pcbStructInfo < bytesNeeded)
1550 *pcbStructInfo = bytesNeeded;
1551 SetLastError(ERROR_MORE_DATA);
1552 ret = FALSE;
1554 else
1556 *pcbStructInfo = bytesNeeded;
1557 value->dwValueType = valueType;
1558 if (dataLen)
1560 DWORD i;
1561 LPWSTR str = (LPWSTR)value->Value.pbData;
1563 assert(value->Value.pbData);
1564 switch (pbEncoded[0])
1566 case ASN_NUMERICSTRING:
1567 case ASN_PRINTABLESTRING:
1568 case ASN_IA5STRING:
1569 case ASN_T61STRING:
1570 case ASN_VIDEOTEXSTRING:
1571 case ASN_GRAPHICSTRING:
1572 case ASN_VISIBLESTRING:
1573 case ASN_GENERALSTRING:
1574 value->Value.cbData = dataLen * 2;
1575 for (i = 0; i < dataLen; i++)
1576 str[i] = pbEncoded[1 + lenBytes + i];
1577 break;
1578 case ASN_UNIVERSALSTRING:
1579 value->Value.cbData = dataLen / 2;
1580 for (i = 0; i < dataLen / 4; i++)
1581 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1582 | pbEncoded[1 + lenBytes + 2 * i + 3];
1583 break;
1584 case ASN_BMPSTRING:
1585 value->Value.cbData = dataLen;
1586 for (i = 0; i < dataLen / 2; i++)
1587 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1588 pbEncoded[1 + lenBytes + 2 * i + 1];
1589 break;
1590 case ASN_UTF8STRING:
1591 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1592 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1593 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1594 break;
1597 else
1599 value->Value.cbData = 0;
1600 value->Value.pbData = NULL;
1604 return ret;
1607 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1608 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1609 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1611 BOOL ret = TRUE;
1613 __TRY
1615 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1616 lpszStructType, pbEncoded, cbEncoded,
1617 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1618 if (ret && pvStructInfo)
1620 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1621 pcbStructInfo, *pcbStructInfo);
1622 if (ret)
1624 CERT_NAME_VALUE *value;
1626 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1627 pvStructInfo = *(BYTE **)pvStructInfo;
1628 value = (CERT_NAME_VALUE *)pvStructInfo;
1629 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1630 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1631 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1632 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1633 pcbStructInfo);
1637 __EXCEPT_PAGE_FAULT
1639 SetLastError(STATUS_ACCESS_VIOLATION);
1640 ret = FALSE;
1642 __ENDTRY
1643 return ret;
1646 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1647 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1648 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1650 BOOL ret;
1651 struct AsnDecodeSequenceItem items[] = {
1652 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1653 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1654 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1655 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1656 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1657 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1659 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1661 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1662 pvStructInfo, *pcbStructInfo);
1664 if (attr)
1665 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1666 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1667 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1668 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1669 if (attr)
1671 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1672 debugstr_a(attr->pszObjId));
1673 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1675 TRACE("returning %d (%08x)\n", ret, GetLastError());
1676 return ret;
1679 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1680 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1681 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1683 BOOL ret = TRUE;
1684 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1685 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1686 offsetof(CERT_RDN_ATTR, pszObjId) };
1687 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1689 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1690 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1691 return ret;
1694 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1695 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1696 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1698 BOOL ret = TRUE;
1700 __TRY
1702 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1703 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1704 offsetof(CERT_RDN, rgRDNAttr) };
1706 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1707 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1709 __EXCEPT_PAGE_FAULT
1711 SetLastError(STATUS_ACCESS_VIOLATION);
1712 ret = FALSE;
1714 __ENDTRY
1715 return ret;
1718 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
1719 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1720 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1722 BOOL ret;
1723 struct AsnDecodeSequenceItem items[] = {
1724 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1725 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1726 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1727 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1728 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1729 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1731 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1733 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1734 pvStructInfo, *pcbStructInfo);
1736 if (attr)
1737 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1738 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1739 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1740 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1741 if (attr)
1743 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1744 debugstr_a(attr->pszObjId));
1745 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1747 TRACE("returning %d (%08x)\n", ret, GetLastError());
1748 return ret;
1751 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
1752 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1753 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1755 BOOL ret = TRUE;
1756 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1757 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1758 offsetof(CERT_RDN_ATTR, pszObjId) };
1759 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1761 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1762 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1763 return ret;
1766 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1767 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1768 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1770 BOOL ret = TRUE;
1772 __TRY
1774 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1775 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1776 offsetof(CERT_RDN, rgRDNAttr) };
1778 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1779 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1781 __EXCEPT_PAGE_FAULT
1783 SetLastError(STATUS_ACCESS_VIOLATION);
1784 ret = FALSE;
1786 __ENDTRY
1787 return ret;
1790 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1791 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1792 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1794 BOOL ret = TRUE;
1795 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1797 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1798 pDecodePara, pvStructInfo, *pcbStructInfo);
1800 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1801 bytesNeeded += cbEncoded;
1802 if (!pvStructInfo)
1803 *pcbStructInfo = bytesNeeded;
1804 else if (*pcbStructInfo < bytesNeeded)
1806 SetLastError(ERROR_MORE_DATA);
1807 *pcbStructInfo = bytesNeeded;
1808 ret = FALSE;
1810 else
1812 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1814 *pcbStructInfo = bytesNeeded;
1815 blob->cbData = cbEncoded;
1816 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1817 blob->pbData = (LPBYTE)pbEncoded;
1818 else
1820 assert(blob->pbData);
1821 memcpy(blob->pbData, pbEncoded, blob->cbData);
1824 return ret;
1827 static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType,
1828 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1829 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1831 BOOL ret;
1832 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
1833 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1834 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1836 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1837 pDecodePara, pvStructInfo, *pcbStructInfo);
1839 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1840 pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
1841 return ret;
1844 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1845 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1846 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1848 BOOL ret = FALSE;
1850 __TRY
1852 struct AsnDecodeSequenceItem items[] = {
1853 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1854 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1855 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1856 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1857 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1858 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1860 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1862 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1863 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1864 pDecodePara, pvStructInfo, pcbStructInfo, attr ? attr->pszObjId :
1865 NULL);
1867 __EXCEPT_PAGE_FAULT
1869 SetLastError(STATUS_ACCESS_VIOLATION);
1871 __ENDTRY
1872 TRACE("returning %d\n", ret);
1873 return ret;
1876 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal(
1877 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1878 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1879 void *pvStructInfo, DWORD *pcbStructInfo)
1881 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodePKCSAttribute,
1882 sizeof(CRYPT_ATTRIBUTE), TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
1883 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1884 BOOL ret;
1886 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1887 pDecodePara, pvStructInfo, pcbStructInfo, attrs ? attrs->rgAttr :
1888 NULL);
1889 return ret;
1892 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
1893 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1894 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1896 BOOL ret = FALSE;
1898 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1899 pDecodePara, pvStructInfo, *pcbStructInfo);
1901 __TRY
1903 DWORD bytesNeeded;
1905 if (!cbEncoded)
1906 SetLastError(CRYPT_E_ASN1_EOD);
1907 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
1908 SetLastError(CRYPT_E_ASN1_CORRUPT);
1909 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(
1910 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1911 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1913 if (!pvStructInfo)
1914 *pcbStructInfo = bytesNeeded;
1915 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1916 pvStructInfo, pcbStructInfo, bytesNeeded)))
1918 PCRYPT_ATTRIBUTES attrs;
1920 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1921 pvStructInfo = *(BYTE **)pvStructInfo;
1922 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1923 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
1924 sizeof(CRYPT_ATTRIBUTES));
1925 ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1926 lpszStructType, pbEncoded, cbEncoded,
1927 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1928 &bytesNeeded);
1932 __EXCEPT_PAGE_FAULT
1934 SetLastError(STATUS_ACCESS_VIOLATION);
1936 __ENDTRY
1937 TRACE("returning %d\n", ret);
1938 return ret;
1941 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1942 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1943 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1945 CRYPT_ALGORITHM_IDENTIFIER *algo =
1946 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1947 BOOL ret = TRUE;
1948 struct AsnDecodeSequenceItem items[] = {
1949 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1950 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1951 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1952 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1953 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1954 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1957 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1958 pDecodePara, pvStructInfo, *pcbStructInfo);
1960 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1961 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1962 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1963 if (ret && pvStructInfo)
1965 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1966 debugstr_a(algo->pszObjId));
1968 return ret;
1971 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1972 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1973 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1975 BOOL ret = TRUE;
1976 struct AsnDecodeSequenceItem items[] = {
1977 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1978 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1979 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1980 Algorithm.pszObjId) },
1981 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1982 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1983 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1985 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1987 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1988 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1989 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1990 info->Algorithm.Parameters.pbData : NULL);
1991 return ret;
1994 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1995 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1996 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1998 BOOL ret = TRUE;
2000 __TRY
2002 DWORD bytesNeeded;
2004 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2005 lpszStructType, pbEncoded, cbEncoded,
2006 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2008 if (!pvStructInfo)
2009 *pcbStructInfo = bytesNeeded;
2010 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2011 pvStructInfo, pcbStructInfo, bytesNeeded)))
2013 PCERT_PUBLIC_KEY_INFO info;
2015 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2016 pvStructInfo = *(BYTE **)pvStructInfo;
2017 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2018 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2019 sizeof(CERT_PUBLIC_KEY_INFO);
2020 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2021 lpszStructType, pbEncoded, cbEncoded,
2022 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2023 &bytesNeeded);
2027 __EXCEPT_PAGE_FAULT
2029 SetLastError(STATUS_ACCESS_VIOLATION);
2030 ret = FALSE;
2032 __ENDTRY
2033 return ret;
2036 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2037 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2038 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2040 BOOL ret;
2042 if (cbEncoded < 3)
2044 SetLastError(CRYPT_E_ASN1_CORRUPT);
2045 return FALSE;
2047 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2049 SetLastError(CRYPT_E_ASN1_CORRUPT);
2050 return FALSE;
2052 if (pbEncoded[1] > 1)
2054 SetLastError(CRYPT_E_ASN1_CORRUPT);
2055 return FALSE;
2057 if (!pvStructInfo)
2059 *pcbStructInfo = sizeof(BOOL);
2060 ret = TRUE;
2062 else if (*pcbStructInfo < sizeof(BOOL))
2064 *pcbStructInfo = sizeof(BOOL);
2065 SetLastError(ERROR_MORE_DATA);
2066 ret = FALSE;
2068 else
2070 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2071 ret = TRUE;
2073 TRACE("returning %d (%08x)\n", ret, GetLastError());
2074 return ret;
2077 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
2078 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2079 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2081 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2082 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2083 BOOL ret;
2085 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2086 pDecodePara, pvStructInfo, *pcbStructInfo);
2088 if (cbEncoded < 2)
2090 SetLastError(CRYPT_E_ASN1_CORRUPT);
2091 return FALSE;
2093 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2094 if (1 + lenBytes > cbEncoded)
2096 SetLastError(CRYPT_E_ASN1_CORRUPT);
2097 return FALSE;
2099 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2101 switch (pbEncoded[0] & ASN_TYPE_MASK)
2103 case 1: /* rfc822Name */
2104 case 2: /* dNSName */
2105 case 6: /* uniformResourceIdentifier */
2106 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2107 break;
2108 case 4: /* directoryName */
2109 case 7: /* iPAddress */
2110 bytesNeeded += dataLen;
2111 break;
2112 case 8: /* registeredID */
2113 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, NULL,
2114 pbEncoded, cbEncoded, 0, NULL, NULL, &dataLen);
2115 if (ret)
2117 /* FIXME: ugly, shouldn't need to know internals of OID decode
2118 * function to use it.
2120 bytesNeeded += dataLen - sizeof(LPSTR);
2122 break;
2123 case 0: /* otherName */
2124 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2125 SetLastError(CRYPT_E_ASN1_BADTAG);
2126 ret = FALSE;
2127 break;
2128 case 3: /* x400Address, unimplemented */
2129 case 5: /* ediPartyName, unimplemented */
2130 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2131 SetLastError(CRYPT_E_ASN1_BADTAG);
2132 ret = FALSE;
2133 break;
2134 default:
2135 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2136 SetLastError(CRYPT_E_ASN1_CORRUPT);
2137 ret = FALSE;
2139 if (ret)
2141 if (!entry)
2142 *pcbStructInfo = bytesNeeded;
2143 else if (*pcbStructInfo < bytesNeeded)
2145 *pcbStructInfo = bytesNeeded;
2146 SetLastError(ERROR_MORE_DATA);
2147 ret = FALSE;
2149 else
2151 *pcbStructInfo = bytesNeeded;
2152 /* MS used values one greater than the asn1 ones.. sigh */
2153 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2154 switch (pbEncoded[0] & ASN_TYPE_MASK)
2156 case 1: /* rfc822Name */
2157 case 2: /* dNSName */
2158 case 6: /* uniformResourceIdentifier */
2160 DWORD i;
2162 for (i = 0; i < dataLen; i++)
2163 entry->u.pwszURL[i] =
2164 (WCHAR)pbEncoded[1 + lenBytes + i];
2165 entry->u.pwszURL[i] = 0;
2166 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2167 debugstr_w(entry->u.pwszURL));
2168 break;
2170 case 4: /* directoryName */
2171 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2172 /* The data are memory-equivalent with the IPAddress case,
2173 * fall-through
2175 case 7: /* iPAddress */
2176 /* The next data pointer is in the pwszURL spot, that is,
2177 * the first 4 bytes. Need to move it to the next spot.
2179 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2180 entry->u.IPAddress.cbData = dataLen;
2181 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2182 dataLen);
2183 break;
2184 case 8: /* registeredID */
2185 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, NULL,
2186 pbEncoded, cbEncoded, 0, NULL, &entry->u.pszRegisteredID,
2187 &dataLen);
2188 break;
2193 return ret;
2196 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2197 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2198 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2200 BOOL ret = TRUE;
2201 struct AsnArrayDescriptor arrayDesc = { 0,
2202 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2203 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2204 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2206 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2207 pDecodePara, pvStructInfo, *pcbStructInfo);
2209 if (info)
2210 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2211 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2212 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2213 return ret;
2216 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2217 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2218 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2220 BOOL ret;
2222 __TRY
2224 struct AsnDecodeSequenceItem items[] = {
2225 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2226 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2227 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2228 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2229 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2230 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2231 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2232 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2233 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2234 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2235 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2238 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2239 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2240 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2242 __EXCEPT_PAGE_FAULT
2244 SetLastError(STATUS_ACCESS_VIOLATION);
2245 ret = FALSE;
2247 __ENDTRY
2248 return ret;
2251 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2252 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2253 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2255 BOOL ret;
2257 __TRY
2259 struct AsnDecodeSequenceItem items[] = {
2260 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2261 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2262 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2263 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2264 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2265 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2266 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2267 AuthorityCertIssuer.rgAltEntry), 0 },
2268 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2269 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2270 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2271 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2272 AuthorityCertSerialNumber.pbData), 0 },
2275 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2276 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2277 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2279 __EXCEPT_PAGE_FAULT
2281 SetLastError(STATUS_ACCESS_VIOLATION);
2282 ret = FALSE;
2284 __ENDTRY
2285 return ret;
2288 static BOOL WINAPI CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType,
2289 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2290 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2292 BOOL ret;
2293 DWORD dataLen;
2295 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2296 pDecodePara, pvStructInfo, *pcbStructInfo);
2298 /* The caller has already checked the tag, no need to check it again.
2299 * Check the outer length is valid by calling CRYPT_GetLen:
2301 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2303 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2304 DWORD innerLen;
2306 pbEncoded += 1 + lenBytes;
2307 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2308 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2310 ret = CRYPT_AsnDecodeCopyBytes(dwCertEncodingType, NULL,
2311 pbEncoded, dataLen, dwFlags, pDecodePara, pvStructInfo,
2312 pcbStructInfo);
2315 return ret;
2318 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfoInternal(
2319 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2320 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2321 void *pvStructInfo, DWORD *pcbStructInfo)
2323 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2324 struct AsnDecodeSequenceItem items[] = {
2325 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2326 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2327 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2328 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2329 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2330 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2331 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2333 BOOL ret;
2335 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2336 pDecodePara, pvStructInfo, *pcbStructInfo);
2338 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2339 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2340 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->pszObjId : NULL);
2341 return ret;
2344 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2345 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2346 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2348 BOOL ret = FALSE;
2350 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2351 pDecodePara, pvStructInfo, *pcbStructInfo);
2353 __TRY
2355 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2356 lpszStructType, pbEncoded, cbEncoded,
2357 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
2358 if (ret && pvStructInfo)
2360 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2361 pcbStructInfo, *pcbStructInfo);
2362 if (ret)
2364 CRYPT_CONTENT_INFO *info;
2366 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2367 pvStructInfo = *(BYTE **)pvStructInfo;
2368 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2369 info->pszObjId = (LPSTR)((BYTE *)info +
2370 sizeof(CRYPT_CONTENT_INFO));
2371 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2372 lpszStructType, pbEncoded, cbEncoded,
2373 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2374 pcbStructInfo);
2378 __EXCEPT_PAGE_FAULT
2380 SetLastError(STATUS_ACCESS_VIOLATION);
2382 __ENDTRY
2383 return ret;
2386 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2387 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2388 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2390 BOOL ret;
2391 struct AsnDecodeSequenceItem items[] = {
2392 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version), CRYPT_AsnDecodeInt,
2393 sizeof(DWORD), FALSE, FALSE, 0, 0 },
2394 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2395 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2396 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2397 0 },
2398 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2399 CRYPT_AsnDecodePKCSContentInfoInternal,
2400 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2401 ContentInfo.pszObjId), 0 },
2402 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2403 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2404 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2407 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
2408 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2409 pDecodePara, digestedData, pcbDigestedData, NULL);
2410 return ret;
2413 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2414 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2415 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2417 BOOL ret = TRUE;
2419 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2420 pDecodePara, pvStructInfo, *pcbStructInfo);
2422 __TRY
2424 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2425 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2426 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2428 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2429 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2431 __EXCEPT_PAGE_FAULT
2433 SetLastError(STATUS_ACCESS_VIOLATION);
2434 ret = FALSE;
2436 __ENDTRY
2437 return ret;
2440 struct PATH_LEN_CONSTRAINT
2442 BOOL fPathLenConstraint;
2443 DWORD dwPathLenConstraint;
2446 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2447 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2448 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2450 BOOL ret = TRUE;
2452 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2453 pvStructInfo, *pcbStructInfo);
2455 if (cbEncoded)
2457 if (pbEncoded[0] == ASN_INTEGER)
2459 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2461 if (!pvStructInfo)
2462 *pcbStructInfo = bytesNeeded;
2463 else if (*pcbStructInfo < bytesNeeded)
2465 SetLastError(ERROR_MORE_DATA);
2466 *pcbStructInfo = bytesNeeded;
2467 ret = FALSE;
2469 else
2471 struct PATH_LEN_CONSTRAINT *constraint =
2472 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2473 DWORD size = sizeof(constraint->dwPathLenConstraint);
2475 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2476 pbEncoded, cbEncoded, 0, NULL,
2477 &constraint->dwPathLenConstraint, &size);
2478 if (ret)
2479 constraint->fPathLenConstraint = TRUE;
2480 TRACE("got an int, dwPathLenConstraint is %d\n",
2481 constraint->dwPathLenConstraint);
2484 else
2486 SetLastError(CRYPT_E_ASN1_CORRUPT);
2487 ret = FALSE;
2490 TRACE("returning %d (%08x)\n", ret, GetLastError());
2491 return ret;
2494 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2495 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2496 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2498 BOOL ret;
2499 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2500 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2501 offsetof(CERT_NAME_BLOB, pbData) };
2502 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2504 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2505 pDecodePara, pvStructInfo, *pcbStructInfo);
2507 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2508 pDecodePara, pvStructInfo, pcbStructInfo,
2509 entries ? entries->rgItems : NULL);
2510 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2511 return ret;
2514 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2515 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2516 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2518 BOOL ret;
2520 __TRY
2522 struct AsnDecodeSequenceItem items[] = {
2523 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2524 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2525 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2526 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2527 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2528 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2529 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2530 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2531 sizeof(struct GenericArray), TRUE, TRUE,
2532 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2535 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2536 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2537 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2539 __EXCEPT_PAGE_FAULT
2541 SetLastError(STATUS_ACCESS_VIOLATION);
2542 ret = FALSE;
2544 __ENDTRY
2545 return ret;
2548 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2549 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2550 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2552 BOOL ret;
2554 __TRY
2556 struct AsnDecodeSequenceItem items[] = {
2557 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2558 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2559 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2560 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2561 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2564 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2565 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2566 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2568 __EXCEPT_PAGE_FAULT
2570 SetLastError(STATUS_ACCESS_VIOLATION);
2571 ret = FALSE;
2573 __ENDTRY
2574 return ret;
2577 #define RSA1_MAGIC 0x31415352
2579 struct DECODED_RSA_PUB_KEY
2581 DWORD pubexp;
2582 CRYPT_INTEGER_BLOB modulus;
2585 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2586 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2587 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2589 BOOL ret;
2591 __TRY
2593 struct AsnDecodeSequenceItem items[] = {
2594 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2595 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2596 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2597 0 },
2598 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2599 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2601 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2602 DWORD size = 0;
2604 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2605 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2606 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2607 if (ret)
2609 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2610 decodedKey->modulus.cbData;
2612 if (!pvStructInfo)
2614 *pcbStructInfo = bytesNeeded;
2615 ret = TRUE;
2617 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2618 pvStructInfo, pcbStructInfo, bytesNeeded)))
2620 BLOBHEADER *hdr;
2621 RSAPUBKEY *rsaPubKey;
2623 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2624 pvStructInfo = *(BYTE **)pvStructInfo;
2625 hdr = (BLOBHEADER *)pvStructInfo;
2626 hdr->bType = PUBLICKEYBLOB;
2627 hdr->bVersion = CUR_BLOB_VERSION;
2628 hdr->reserved = 0;
2629 hdr->aiKeyAlg = CALG_RSA_KEYX;
2630 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2631 sizeof(BLOBHEADER));
2632 rsaPubKey->magic = RSA1_MAGIC;
2633 rsaPubKey->pubexp = decodedKey->pubexp;
2634 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2635 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2636 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2637 decodedKey->modulus.cbData);
2639 LocalFree(decodedKey);
2642 __EXCEPT_PAGE_FAULT
2644 SetLastError(STATUS_ACCESS_VIOLATION);
2645 ret = FALSE;
2647 __ENDTRY
2648 return ret;
2651 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2652 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2653 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2655 BOOL ret;
2656 DWORD bytesNeeded, dataLen;
2658 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2659 pDecodePara, pvStructInfo, *pcbStructInfo);
2661 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2663 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2664 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2665 else
2666 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2667 if (!pvStructInfo)
2668 *pcbStructInfo = bytesNeeded;
2669 else if (*pcbStructInfo < bytesNeeded)
2671 SetLastError(ERROR_MORE_DATA);
2672 *pcbStructInfo = bytesNeeded;
2673 ret = FALSE;
2675 else
2677 CRYPT_DATA_BLOB *blob;
2678 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2680 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2681 blob->cbData = dataLen;
2682 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2683 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2684 else
2686 assert(blob->pbData);
2687 if (blob->cbData)
2688 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2689 blob->cbData);
2693 return ret;
2696 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2697 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2698 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2700 BOOL ret;
2702 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2703 pDecodePara, pvStructInfo, *pcbStructInfo);
2705 __TRY
2707 DWORD bytesNeeded;
2709 if (!cbEncoded)
2711 SetLastError(CRYPT_E_ASN1_CORRUPT);
2712 ret = FALSE;
2714 else if (pbEncoded[0] != ASN_OCTETSTRING)
2716 SetLastError(CRYPT_E_ASN1_BADTAG);
2717 ret = FALSE;
2719 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2720 lpszStructType, pbEncoded, cbEncoded,
2721 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2723 if (!pvStructInfo)
2724 *pcbStructInfo = bytesNeeded;
2725 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2726 pvStructInfo, pcbStructInfo, bytesNeeded)))
2728 CRYPT_DATA_BLOB *blob;
2730 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2731 pvStructInfo = *(BYTE **)pvStructInfo;
2732 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2733 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2734 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2735 lpszStructType, pbEncoded, cbEncoded,
2736 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2737 &bytesNeeded);
2741 __EXCEPT_PAGE_FAULT
2743 SetLastError(STATUS_ACCESS_VIOLATION);
2744 ret = FALSE;
2746 __ENDTRY
2747 return ret;
2750 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2751 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2752 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2754 BOOL ret;
2756 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2757 pDecodePara, pvStructInfo, *pcbStructInfo);
2759 if (pbEncoded[0] == ASN_BITSTRING)
2761 DWORD bytesNeeded, dataLen;
2763 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2765 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2766 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2767 else
2768 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2769 if (!pvStructInfo)
2770 *pcbStructInfo = bytesNeeded;
2771 else if (*pcbStructInfo < bytesNeeded)
2773 *pcbStructInfo = bytesNeeded;
2774 SetLastError(ERROR_MORE_DATA);
2775 ret = FALSE;
2777 else
2779 CRYPT_BIT_BLOB *blob;
2781 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2782 blob->cbData = dataLen - 1;
2783 blob->cUnusedBits = *(pbEncoded + 1 +
2784 GET_LEN_BYTES(pbEncoded[1]));
2785 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2787 blob->pbData = (BYTE *)pbEncoded + 2 +
2788 GET_LEN_BYTES(pbEncoded[1]);
2790 else
2792 assert(blob->pbData);
2793 if (blob->cbData)
2795 BYTE mask = 0xff << blob->cUnusedBits;
2797 memcpy(blob->pbData, pbEncoded + 2 +
2798 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2799 blob->pbData[blob->cbData - 1] &= mask;
2805 else
2807 SetLastError(CRYPT_E_ASN1_BADTAG);
2808 ret = FALSE;
2810 TRACE("returning %d (%08x)\n", ret, GetLastError());
2811 return ret;
2814 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2815 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2816 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2818 BOOL ret;
2820 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2821 pDecodePara, pvStructInfo, pcbStructInfo);
2823 __TRY
2825 DWORD bytesNeeded;
2827 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2828 lpszStructType, pbEncoded, cbEncoded,
2829 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2831 if (!pvStructInfo)
2832 *pcbStructInfo = bytesNeeded;
2833 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2834 pvStructInfo, pcbStructInfo, bytesNeeded)))
2836 CRYPT_BIT_BLOB *blob;
2838 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2839 pvStructInfo = *(BYTE **)pvStructInfo;
2840 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2841 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2842 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2843 lpszStructType, pbEncoded, cbEncoded,
2844 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2845 &bytesNeeded);
2849 __EXCEPT_PAGE_FAULT
2851 SetLastError(STATUS_ACCESS_VIOLATION);
2852 ret = FALSE;
2854 __ENDTRY
2855 TRACE("returning %d (%08x)\n", ret, GetLastError());
2856 return ret;
2859 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2860 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2861 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2863 BOOL ret;
2865 if (!pvStructInfo)
2867 *pcbStructInfo = sizeof(int);
2868 return TRUE;
2870 __TRY
2872 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2873 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2874 DWORD size = sizeof(buf);
2876 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2877 if (pbEncoded[0] != ASN_INTEGER)
2879 SetLastError(CRYPT_E_ASN1_BADTAG);
2880 ret = FALSE;
2882 else
2883 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2884 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
2885 &size);
2886 if (ret)
2888 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2889 pvStructInfo, pcbStructInfo, sizeof(int))))
2891 int val, i;
2893 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2894 pvStructInfo = *(BYTE **)pvStructInfo;
2895 if (blob->pbData[blob->cbData - 1] & 0x80)
2897 /* initialize to a negative value to sign-extend */
2898 val = -1;
2900 else
2901 val = 0;
2902 for (i = 0; i < blob->cbData; i++)
2904 val <<= 8;
2905 val |= blob->pbData[blob->cbData - i - 1];
2907 memcpy(pvStructInfo, &val, sizeof(int));
2910 else if (GetLastError() == ERROR_MORE_DATA)
2911 SetLastError(CRYPT_E_ASN1_LARGE);
2913 __EXCEPT_PAGE_FAULT
2915 SetLastError(STATUS_ACCESS_VIOLATION);
2916 ret = FALSE;
2918 __ENDTRY
2919 return ret;
2922 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2923 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2924 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2926 BOOL ret;
2927 DWORD bytesNeeded, dataLen;
2929 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2931 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2933 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2934 if (!pvStructInfo)
2935 *pcbStructInfo = bytesNeeded;
2936 else if (*pcbStructInfo < bytesNeeded)
2938 *pcbStructInfo = bytesNeeded;
2939 SetLastError(ERROR_MORE_DATA);
2940 ret = FALSE;
2942 else
2944 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2946 blob->cbData = dataLen;
2947 assert(blob->pbData);
2948 if (blob->cbData)
2950 DWORD i;
2952 for (i = 0; i < blob->cbData; i++)
2954 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2955 dataLen - i - 1);
2960 return ret;
2963 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2964 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2965 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2967 BOOL ret;
2969 __TRY
2971 DWORD bytesNeeded;
2973 if (pbEncoded[0] != ASN_INTEGER)
2975 SetLastError(CRYPT_E_ASN1_BADTAG);
2976 ret = FALSE;
2978 else
2979 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2980 lpszStructType, pbEncoded, cbEncoded,
2981 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
2982 if (ret)
2984 if (!pvStructInfo)
2985 *pcbStructInfo = bytesNeeded;
2986 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2987 pvStructInfo, pcbStructInfo, bytesNeeded)))
2989 CRYPT_INTEGER_BLOB *blob;
2991 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2992 pvStructInfo = *(BYTE **)pvStructInfo;
2993 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2994 blob->pbData = (BYTE *)pvStructInfo +
2995 sizeof(CRYPT_INTEGER_BLOB);
2996 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2997 lpszStructType, pbEncoded, cbEncoded,
2998 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2999 &bytesNeeded);
3003 __EXCEPT_PAGE_FAULT
3005 SetLastError(STATUS_ACCESS_VIOLATION);
3006 ret = FALSE;
3008 __ENDTRY
3009 return ret;
3012 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
3013 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3014 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3015 void *pvStructInfo, DWORD *pcbStructInfo)
3017 BOOL ret;
3019 if (pbEncoded[0] == ASN_INTEGER)
3021 DWORD bytesNeeded, dataLen;
3023 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3025 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3027 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3028 if (!pvStructInfo)
3029 *pcbStructInfo = bytesNeeded;
3030 else if (*pcbStructInfo < bytesNeeded)
3032 *pcbStructInfo = bytesNeeded;
3033 SetLastError(ERROR_MORE_DATA);
3034 ret = FALSE;
3036 else
3038 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3040 blob->cbData = dataLen;
3041 assert(blob->pbData);
3042 /* remove leading zero byte if it exists */
3043 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3045 blob->cbData--;
3046 blob->pbData++;
3048 if (blob->cbData)
3050 DWORD i;
3052 for (i = 0; i < blob->cbData; i++)
3054 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3055 dataLen - i - 1);
3061 else
3063 SetLastError(CRYPT_E_ASN1_BADTAG);
3064 ret = FALSE;
3066 return ret;
3069 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3070 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3071 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3073 BOOL ret;
3075 __TRY
3077 DWORD bytesNeeded;
3079 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3080 lpszStructType, pbEncoded, cbEncoded,
3081 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
3083 if (!pvStructInfo)
3084 *pcbStructInfo = bytesNeeded;
3085 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3086 pvStructInfo, pcbStructInfo, bytesNeeded)))
3088 CRYPT_INTEGER_BLOB *blob;
3090 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3091 pvStructInfo = *(BYTE **)pvStructInfo;
3092 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3093 blob->pbData = (BYTE *)pvStructInfo +
3094 sizeof(CRYPT_INTEGER_BLOB);
3095 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3096 lpszStructType, pbEncoded, cbEncoded,
3097 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3098 &bytesNeeded);
3102 __EXCEPT_PAGE_FAULT
3104 SetLastError(STATUS_ACCESS_VIOLATION);
3105 ret = FALSE;
3107 __ENDTRY
3108 return ret;
3111 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3112 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3113 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3115 BOOL ret;
3117 if (!pvStructInfo)
3119 *pcbStructInfo = sizeof(int);
3120 return TRUE;
3122 __TRY
3124 if (pbEncoded[0] == ASN_ENUMERATED)
3126 unsigned int val = 0, i;
3128 if (cbEncoded <= 1)
3130 SetLastError(CRYPT_E_ASN1_EOD);
3131 ret = FALSE;
3133 else if (pbEncoded[1] == 0)
3135 SetLastError(CRYPT_E_ASN1_CORRUPT);
3136 ret = FALSE;
3138 else
3140 /* A little strange looking, but we have to accept a sign byte:
3141 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3142 * assuming a small length is okay here, it has to be in short
3143 * form.
3145 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3147 SetLastError(CRYPT_E_ASN1_LARGE);
3148 return FALSE;
3150 for (i = 0; i < pbEncoded[1]; i++)
3152 val <<= 8;
3153 val |= pbEncoded[2 + i];
3155 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3156 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3158 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3159 pvStructInfo = *(BYTE **)pvStructInfo;
3160 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3164 else
3166 SetLastError(CRYPT_E_ASN1_BADTAG);
3167 ret = FALSE;
3170 __EXCEPT_PAGE_FAULT
3172 SetLastError(STATUS_ACCESS_VIOLATION);
3173 ret = FALSE;
3175 __ENDTRY
3176 return ret;
3179 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3180 * if it fails.
3182 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3183 do { \
3184 BYTE i; \
3186 (word) = 0; \
3187 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3189 if (!isdigit(*(pbEncoded))) \
3191 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3192 ret = FALSE; \
3194 else \
3196 (word) *= 10; \
3197 (word) += *(pbEncoded)++ - '0'; \
3200 } while (0)
3202 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3203 SYSTEMTIME *sysTime)
3205 BOOL ret;
3207 __TRY
3209 ret = TRUE;
3210 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3212 WORD hours, minutes = 0;
3213 BYTE sign = *pbEncoded++;
3215 len--;
3216 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3217 if (ret && hours >= 24)
3219 SetLastError(CRYPT_E_ASN1_CORRUPT);
3220 ret = FALSE;
3222 else if (len >= 2)
3224 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3225 if (ret && minutes >= 60)
3227 SetLastError(CRYPT_E_ASN1_CORRUPT);
3228 ret = FALSE;
3231 if (ret)
3233 if (sign == '+')
3235 sysTime->wHour += hours;
3236 sysTime->wMinute += minutes;
3238 else
3240 if (hours > sysTime->wHour)
3242 sysTime->wDay--;
3243 sysTime->wHour = 24 - (hours - sysTime->wHour);
3245 else
3246 sysTime->wHour -= hours;
3247 if (minutes > sysTime->wMinute)
3249 sysTime->wHour--;
3250 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3252 else
3253 sysTime->wMinute -= minutes;
3258 __EXCEPT_PAGE_FAULT
3260 SetLastError(STATUS_ACCESS_VIOLATION);
3261 ret = FALSE;
3263 __ENDTRY
3264 return ret;
3267 #define MIN_ENCODED_TIME_LENGTH 10
3269 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3270 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3271 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3273 BOOL ret;
3275 if (!pvStructInfo)
3277 *pcbStructInfo = sizeof(FILETIME);
3278 return TRUE;
3280 __TRY
3282 ret = TRUE;
3283 if (pbEncoded[0] == ASN_UTCTIME)
3285 if (cbEncoded <= 1)
3287 SetLastError(CRYPT_E_ASN1_EOD);
3288 ret = FALSE;
3290 else if (pbEncoded[1] > 0x7f)
3292 /* long-form date strings really can't be valid */
3293 SetLastError(CRYPT_E_ASN1_CORRUPT);
3294 ret = FALSE;
3296 else
3298 SYSTEMTIME sysTime = { 0 };
3299 BYTE len = pbEncoded[1];
3301 if (len < MIN_ENCODED_TIME_LENGTH)
3303 SetLastError(CRYPT_E_ASN1_CORRUPT);
3304 ret = FALSE;
3306 else
3308 pbEncoded += 2;
3309 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3310 if (sysTime.wYear >= 50)
3311 sysTime.wYear += 1900;
3312 else
3313 sysTime.wYear += 2000;
3314 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3315 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3316 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3317 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3318 if (ret && len > 0)
3320 if (len >= 2 && isdigit(*pbEncoded) &&
3321 isdigit(*(pbEncoded + 1)))
3322 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3323 sysTime.wSecond);
3324 else if (isdigit(*pbEncoded))
3325 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3326 sysTime.wSecond);
3327 if (ret)
3328 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3329 &sysTime);
3331 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3332 pDecodePara, pvStructInfo, pcbStructInfo,
3333 sizeof(FILETIME))))
3335 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3336 pvStructInfo = *(BYTE **)pvStructInfo;
3337 ret = SystemTimeToFileTime(&sysTime,
3338 (FILETIME *)pvStructInfo);
3343 else
3345 SetLastError(CRYPT_E_ASN1_BADTAG);
3346 ret = FALSE;
3349 __EXCEPT_PAGE_FAULT
3351 SetLastError(STATUS_ACCESS_VIOLATION);
3352 ret = FALSE;
3354 __ENDTRY
3355 return ret;
3358 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3359 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3360 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3362 BOOL ret;
3364 if (!pvStructInfo)
3366 *pcbStructInfo = sizeof(FILETIME);
3367 return TRUE;
3369 __TRY
3371 ret = TRUE;
3372 if (pbEncoded[0] == ASN_GENERALTIME)
3374 if (cbEncoded <= 1)
3376 SetLastError(CRYPT_E_ASN1_EOD);
3377 ret = FALSE;
3379 else if (pbEncoded[1] > 0x7f)
3381 /* long-form date strings really can't be valid */
3382 SetLastError(CRYPT_E_ASN1_CORRUPT);
3383 ret = FALSE;
3385 else
3387 BYTE len = pbEncoded[1];
3389 if (len < MIN_ENCODED_TIME_LENGTH)
3391 SetLastError(CRYPT_E_ASN1_CORRUPT);
3392 ret = FALSE;
3394 else
3396 SYSTEMTIME sysTime = { 0 };
3398 pbEncoded += 2;
3399 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3400 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3401 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3402 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3403 if (ret && len > 0)
3405 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3406 sysTime.wMinute);
3407 if (ret && len > 0)
3408 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3409 sysTime.wSecond);
3410 if (ret && len > 0 && (*pbEncoded == '.' ||
3411 *pbEncoded == ','))
3413 BYTE digits;
3415 pbEncoded++;
3416 len--;
3417 /* workaround macro weirdness */
3418 digits = min(len, 3);
3419 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3420 sysTime.wMilliseconds);
3422 if (ret)
3423 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3424 &sysTime);
3426 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3427 pDecodePara, pvStructInfo, pcbStructInfo,
3428 sizeof(FILETIME))))
3430 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3431 pvStructInfo = *(BYTE **)pvStructInfo;
3432 ret = SystemTimeToFileTime(&sysTime,
3433 (FILETIME *)pvStructInfo);
3438 else
3440 SetLastError(CRYPT_E_ASN1_BADTAG);
3441 ret = FALSE;
3444 __EXCEPT_PAGE_FAULT
3446 SetLastError(STATUS_ACCESS_VIOLATION);
3447 ret = FALSE;
3449 __ENDTRY
3450 return ret;
3453 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3454 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3455 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3457 BOOL ret;
3459 __TRY
3461 if (pbEncoded[0] == ASN_UTCTIME)
3462 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3463 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3464 pcbStructInfo);
3465 else if (pbEncoded[0] == ASN_GENERALTIME)
3466 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3467 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3468 pvStructInfo, pcbStructInfo);
3469 else
3471 SetLastError(CRYPT_E_ASN1_BADTAG);
3472 ret = FALSE;
3475 __EXCEPT_PAGE_FAULT
3477 SetLastError(STATUS_ACCESS_VIOLATION);
3478 ret = FALSE;
3480 __ENDTRY
3481 return ret;
3484 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3485 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3486 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3488 BOOL ret = TRUE;
3490 __TRY
3492 if (pbEncoded[0] == ASN_SEQUENCEOF)
3494 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3496 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3498 BYTE lenBytes;
3499 const BYTE *ptr;
3501 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3502 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3503 cValue = 0;
3504 ptr = pbEncoded + 1 + lenBytes;
3505 remainingLen = dataLen;
3506 while (ret && remainingLen)
3508 DWORD nextLen;
3510 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3511 if (ret)
3513 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3515 remainingLen -= 1 + nextLenBytes + nextLen;
3516 ptr += 1 + nextLenBytes + nextLen;
3517 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3518 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3519 bytesNeeded += 1 + nextLenBytes + nextLen;
3520 cValue++;
3523 if (ret)
3525 CRYPT_SEQUENCE_OF_ANY *seq;
3526 BYTE *nextPtr;
3527 DWORD i;
3529 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3530 pvStructInfo, pcbStructInfo, bytesNeeded)))
3532 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3533 pvStructInfo = *(BYTE **)pvStructInfo;
3534 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3535 seq->cValue = cValue;
3536 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3537 sizeof(*seq));
3538 nextPtr = (BYTE *)seq->rgValue +
3539 cValue * sizeof(CRYPT_DER_BLOB);
3540 ptr = pbEncoded + 1 + lenBytes;
3541 remainingLen = dataLen;
3542 i = 0;
3543 while (ret && remainingLen)
3545 DWORD nextLen;
3547 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3548 if (ret)
3550 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3552 seq->rgValue[i].cbData = 1 + nextLenBytes +
3553 nextLen;
3554 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3555 seq->rgValue[i].pbData = (BYTE *)ptr;
3556 else
3558 seq->rgValue[i].pbData = nextPtr;
3559 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3560 nextLen);
3561 nextPtr += 1 + nextLenBytes + nextLen;
3563 remainingLen -= 1 + nextLenBytes + nextLen;
3564 ptr += 1 + nextLenBytes + nextLen;
3565 i++;
3572 else
3574 SetLastError(CRYPT_E_ASN1_BADTAG);
3575 ret = FALSE;
3578 __EXCEPT_PAGE_FAULT
3580 SetLastError(STATUS_ACCESS_VIOLATION);
3581 ret = FALSE;
3583 __ENDTRY
3584 return ret;
3587 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3588 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3589 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3591 BOOL ret;
3593 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3595 DWORD bytesNeeded, dataLen;
3597 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3599 struct AsnArrayDescriptor arrayDesc = {
3600 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3601 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3602 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3603 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3605 if (dataLen)
3607 DWORD nameLen;
3609 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3610 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3611 0, NULL, NULL, &nameLen, NULL);
3612 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3614 else
3615 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3616 if (!pvStructInfo)
3617 *pcbStructInfo = bytesNeeded;
3618 else if (*pcbStructInfo < bytesNeeded)
3620 *pcbStructInfo = bytesNeeded;
3621 SetLastError(ERROR_MORE_DATA);
3622 ret = FALSE;
3624 else
3626 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3628 if (dataLen)
3630 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3631 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3632 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3633 0, NULL, &name->u.FullName, pcbStructInfo,
3634 name->u.FullName.rgAltEntry);
3636 else
3637 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3641 else
3643 SetLastError(CRYPT_E_ASN1_BADTAG);
3644 ret = FALSE;
3646 return ret;
3649 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3650 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3651 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3653 struct AsnDecodeSequenceItem items[] = {
3654 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3655 DistPointName), CRYPT_AsnDecodeDistPointName,
3656 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3657 DistPointName.u.FullName.rgAltEntry), 0 },
3658 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3659 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3660 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3661 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3662 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3663 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3665 BOOL ret;
3667 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3668 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3669 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3670 return ret;
3673 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3674 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3675 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3677 BOOL ret;
3679 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3680 pDecodePara, pvStructInfo, *pcbStructInfo);
3682 __TRY
3684 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3685 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3686 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3688 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3689 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3691 __EXCEPT_PAGE_FAULT
3693 SetLastError(STATUS_ACCESS_VIOLATION);
3694 ret = FALSE;
3696 __ENDTRY
3697 return ret;
3700 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3701 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3702 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3704 BOOL ret;
3706 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3707 pDecodePara, pvStructInfo, *pcbStructInfo);
3709 __TRY
3711 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3712 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3714 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3715 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3717 __EXCEPT_PAGE_FAULT
3719 SetLastError(STATUS_ACCESS_VIOLATION);
3720 ret = FALSE;
3722 __ENDTRY
3723 return ret;
3726 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3727 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3728 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3730 BOOL ret;
3732 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3733 pDecodePara, pvStructInfo, *pcbStructInfo);
3735 __TRY
3737 struct AsnDecodeSequenceItem items[] = {
3738 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3739 DistPointName), CRYPT_AsnDecodeDistPointName,
3740 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3741 offsetof(CRL_ISSUING_DIST_POINT,
3742 DistPointName.u.FullName.rgAltEntry), 0 },
3743 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3744 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3745 FALSE, 0 },
3746 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3747 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3748 FALSE, 0 },
3749 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3750 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3751 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3752 OnlySomeReasonFlags.pbData), 0 },
3753 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3754 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3757 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3758 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3759 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3761 __EXCEPT_PAGE_FAULT
3763 SetLastError(STATUS_ACCESS_VIOLATION);
3764 ret = FALSE;
3766 __ENDTRY
3767 return ret;
3770 static BOOL WINAPI CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType,
3771 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3772 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3774 BOOL ret;
3775 struct AsnDecodeSequenceItem items[] = {
3776 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
3777 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
3778 Issuer.pbData) },
3779 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
3780 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
3781 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
3783 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3784 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3786 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3787 pDecodePara, pvStructInfo, *pcbStructInfo);
3789 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3790 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3791 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
3792 issuerSerial ? issuerSerial->Issuer.pbData : NULL);
3793 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
3795 SetLastError(CRYPT_E_ASN1_CORRUPT);
3796 ret = FALSE;
3798 TRACE("returning %d\n", ret);
3799 return ret;
3802 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfoInternal(
3803 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3804 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3805 void *pvStructInfo, DWORD *pcbStructInfo)
3807 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
3808 struct AsnDecodeSequenceItem items[] = {
3809 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
3810 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3811 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
3812 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
3813 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
3814 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
3815 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3816 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
3817 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
3818 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
3819 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3820 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
3821 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
3822 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3823 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
3824 HashEncryptionAlgorithm.pszObjId), 0 },
3825 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
3826 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
3827 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
3828 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
3829 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
3830 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3831 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
3833 BOOL ret;
3835 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3836 pDecodePara, pvStructInfo, *pcbStructInfo);
3838 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3839 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3840 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
3841 info ? info->Issuer.pbData : NULL);
3842 return ret;
3845 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
3846 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3847 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3849 BOOL ret = FALSE;
3851 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3852 pDecodePara, pvStructInfo, *pcbStructInfo);
3854 __TRY
3856 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType,
3857 lpszStructType, pbEncoded, cbEncoded,
3858 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
3859 if (ret && pvStructInfo)
3861 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3862 pcbStructInfo, *pcbStructInfo);
3863 if (ret)
3865 CMSG_SIGNER_INFO *info;
3867 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3868 pvStructInfo = *(BYTE **)pvStructInfo;
3869 info = (CMSG_SIGNER_INFO *)pvStructInfo;
3870 info->Issuer.pbData = ((BYTE *)info +
3871 sizeof(CMSG_SIGNER_INFO));
3872 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(dwCertEncodingType,
3873 lpszStructType, pbEncoded, cbEncoded,
3874 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
3875 pcbStructInfo);
3879 __EXCEPT_PAGE_FAULT
3881 SetLastError(STATUS_ACCESS_VIOLATION);
3883 __ENDTRY
3884 TRACE("returning %d\n", ret);
3885 return ret;
3888 static BOOL WINAPI CRYPT_DecodeSignerArray(DWORD dwCertEncodingType,
3889 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3890 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3892 BOOL ret;
3893 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
3894 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
3895 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
3896 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
3898 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3899 pDecodePara, pvStructInfo, *pcbStructInfo);
3901 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3902 pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
3903 return ret;
3906 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
3907 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3908 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
3910 BOOL ret = FALSE;
3911 struct AsnDecodeSequenceItem items[] = {
3912 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version), CRYPT_AsnDecodeInt,
3913 sizeof(DWORD), FALSE, FALSE, 0, 0 },
3914 /* Placeholder for the hash algorithms - redundant with those in the
3915 * signers, so just ignore them.
3917 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
3918 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
3919 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
3920 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
3921 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
3922 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
3923 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
3924 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
3925 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
3926 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
3927 sizeof(struct GenericArray), TRUE, TRUE,
3928 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
3929 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
3930 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
3931 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
3934 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3935 pDecodePara, signedInfo, *pcbSignedInfo);
3937 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3938 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
3939 pDecodePara, signedInfo, pcbSignedInfo, NULL);
3940 TRACE("returning %d\n", ret);
3941 return ret;
3944 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
3945 LPCSTR lpszStructType)
3947 CryptDecodeObjectExFunc decodeFunc = NULL;
3949 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3950 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3952 SetLastError(ERROR_FILE_NOT_FOUND);
3953 return NULL;
3955 if (!HIWORD(lpszStructType))
3957 switch (LOWORD(lpszStructType))
3959 case (WORD)X509_CERT:
3960 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3961 break;
3962 case (WORD)X509_CERT_TO_BE_SIGNED:
3963 decodeFunc = CRYPT_AsnDecodeCert;
3964 break;
3965 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3966 decodeFunc = CRYPT_AsnDecodeCRL;
3967 break;
3968 case (WORD)X509_EXTENSIONS:
3969 decodeFunc = CRYPT_AsnDecodeExtensions;
3970 break;
3971 case (WORD)X509_NAME_VALUE:
3972 decodeFunc = CRYPT_AsnDecodeNameValue;
3973 break;
3974 case (WORD)X509_NAME:
3975 decodeFunc = CRYPT_AsnDecodeName;
3976 break;
3977 case (WORD)X509_PUBLIC_KEY_INFO:
3978 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
3979 break;
3980 case (WORD)X509_AUTHORITY_KEY_ID:
3981 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3982 break;
3983 case (WORD)X509_ALTERNATE_NAME:
3984 decodeFunc = CRYPT_AsnDecodeAltName;
3985 break;
3986 case (WORD)X509_BASIC_CONSTRAINTS:
3987 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3988 break;
3989 case (WORD)X509_BASIC_CONSTRAINTS2:
3990 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3991 break;
3992 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3993 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3994 break;
3995 case (WORD)X509_UNICODE_NAME:
3996 decodeFunc = CRYPT_AsnDecodeUnicodeName;
3997 break;
3998 case (WORD)PKCS_ATTRIBUTE:
3999 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4000 break;
4001 case (WORD)X509_UNICODE_NAME_VALUE:
4002 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4003 break;
4004 case (WORD)X509_OCTET_STRING:
4005 decodeFunc = CRYPT_AsnDecodeOctets;
4006 break;
4007 case (WORD)X509_BITS:
4008 case (WORD)X509_KEY_USAGE:
4009 decodeFunc = CRYPT_AsnDecodeBits;
4010 break;
4011 case (WORD)X509_INTEGER:
4012 decodeFunc = CRYPT_AsnDecodeInt;
4013 break;
4014 case (WORD)X509_MULTI_BYTE_INTEGER:
4015 decodeFunc = CRYPT_AsnDecodeInteger;
4016 break;
4017 case (WORD)X509_MULTI_BYTE_UINT:
4018 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4019 break;
4020 case (WORD)X509_ENUMERATED:
4021 decodeFunc = CRYPT_AsnDecodeEnumerated;
4022 break;
4023 case (WORD)X509_CHOICE_OF_TIME:
4024 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4025 break;
4026 case (WORD)X509_AUTHORITY_KEY_ID2:
4027 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4028 break;
4029 case (WORD)PKCS_CONTENT_INFO:
4030 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4031 break;
4032 case (WORD)X509_SEQUENCE_OF_ANY:
4033 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4034 break;
4035 case (WORD)PKCS_UTC_TIME:
4036 decodeFunc = CRYPT_AsnDecodeUtcTime;
4037 break;
4038 case (WORD)X509_CRL_DIST_POINTS:
4039 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4040 break;
4041 case (WORD)X509_ENHANCED_KEY_USAGE:
4042 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4043 break;
4044 case (WORD)PKCS_ATTRIBUTES:
4045 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4046 break;
4047 case (WORD)X509_ISSUING_DIST_POINT:
4048 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4049 break;
4050 case (WORD)PKCS7_SIGNER_INFO:
4051 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4052 break;
4055 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4056 decodeFunc = CRYPT_AsnDecodeExtensions;
4057 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4058 decodeFunc = CRYPT_AsnDecodeUtcTime;
4059 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4060 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4061 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4062 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4063 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4064 decodeFunc = CRYPT_AsnDecodeEnumerated;
4065 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4066 decodeFunc = CRYPT_AsnDecodeBits;
4067 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4068 decodeFunc = CRYPT_AsnDecodeOctets;
4069 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4070 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4071 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4072 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4073 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4074 decodeFunc = CRYPT_AsnDecodeAltName;
4075 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4076 decodeFunc = CRYPT_AsnDecodeAltName;
4077 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4078 decodeFunc = CRYPT_AsnDecodeAltName;
4079 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4080 decodeFunc = CRYPT_AsnDecodeAltName;
4081 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4082 decodeFunc = CRYPT_AsnDecodeAltName;
4083 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4084 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4085 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4086 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4087 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4088 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4089 return decodeFunc;
4092 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4093 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4095 static HCRYPTOIDFUNCSET set = NULL;
4096 CryptDecodeObjectFunc decodeFunc = NULL;
4098 if (!set)
4099 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4100 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4101 (void **)&decodeFunc, hFunc);
4102 return decodeFunc;
4105 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4106 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4108 static HCRYPTOIDFUNCSET set = NULL;
4109 CryptDecodeObjectExFunc decodeFunc = NULL;
4111 if (!set)
4112 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4113 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4114 (void **)&decodeFunc, hFunc);
4115 return decodeFunc;
4118 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4119 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4120 DWORD *pcbStructInfo)
4122 BOOL ret = FALSE;
4123 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4124 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4125 HCRYPTOIDFUNCADDR hFunc = NULL;
4127 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4128 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4129 pvStructInfo, pcbStructInfo);
4131 if (!pvStructInfo && !pcbStructInfo)
4133 SetLastError(ERROR_INVALID_PARAMETER);
4134 return FALSE;
4136 if (!cbEncoded)
4138 SetLastError(CRYPT_E_ASN1_EOD);
4139 return FALSE;
4141 if (cbEncoded > MAX_ENCODED_LEN)
4143 SetLastError(CRYPT_E_ASN1_LARGE);
4144 return FALSE;
4147 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4148 lpszStructType)))
4150 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4151 debugstr_a(lpszStructType));
4152 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4153 lpszStructType, &hFunc);
4154 if (!pCryptDecodeObject)
4155 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4156 lpszStructType, &hFunc);
4158 if (pCryptDecodeObject)
4159 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4160 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4161 else if (pCryptDecodeObjectEx)
4162 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4163 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4164 pvStructInfo, pcbStructInfo);
4165 if (hFunc)
4166 CryptFreeOIDFunctionAddress(hFunc, 0);
4167 TRACE_(crypt)("returning %d\n", ret);
4168 return ret;
4171 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4172 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4173 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4175 BOOL ret = FALSE;
4176 CryptDecodeObjectExFunc decodeFunc;
4177 HCRYPTOIDFUNCADDR hFunc = NULL;
4179 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4180 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4181 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4183 if (!pvStructInfo && !pcbStructInfo)
4185 SetLastError(ERROR_INVALID_PARAMETER);
4186 return FALSE;
4188 if (!cbEncoded)
4190 SetLastError(CRYPT_E_ASN1_EOD);
4191 return FALSE;
4193 if (cbEncoded > MAX_ENCODED_LEN)
4195 SetLastError(CRYPT_E_ASN1_LARGE);
4196 return FALSE;
4199 SetLastError(NOERROR);
4200 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4201 *(BYTE **)pvStructInfo = NULL;
4202 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4203 if (!decodeFunc)
4205 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4206 debugstr_a(lpszStructType));
4207 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4208 &hFunc);
4210 if (decodeFunc)
4211 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4212 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4213 else
4215 CryptDecodeObjectFunc pCryptDecodeObject =
4216 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4218 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4219 * directly, as that could cause an infinite loop.
4221 if (pCryptDecodeObject)
4223 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4225 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4226 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4227 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4228 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4229 ret = pCryptDecodeObject(dwCertEncodingType,
4230 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4231 *(BYTE **)pvStructInfo, pcbStructInfo);
4233 else
4234 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4235 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4238 if (hFunc)
4239 CryptFreeOIDFunctionAddress(hFunc, 0);
4240 TRACE_(crypt)("returning %d\n", ret);
4241 return ret;