crypt32: Don't check tag in CRYPT_DecodeDERArray, caller already does.
[wine.git] / dlls / crypt32 / decode.c
blobf66ae858aef649afd90c46c15ae02688f6aa5af5
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(crypt);
58 struct GenericArray
60 DWORD cItems;
61 BYTE *rgItems;
64 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
65 DWORD, DWORD, void *, DWORD *);
66 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
67 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
69 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
70 * The dwCertEncodingType and lpszStructType are ignored by the built-in
71 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
72 * since it must call functions in external DLLs that follow these signatures.
74 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
75 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
76 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
77 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
78 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
79 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
80 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
81 * time, doesn't do memory allocation, and doesn't do exception handling.
82 * (This isn't intended to be the externally-called one.)
84 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
86 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
87 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
88 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
89 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
90 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
91 /* Internal function */
92 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
93 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
94 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
97 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
98 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
99 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
100 * member has been initialized, doesn't do exception handling, and doesn't do
101 * memory allocation.
103 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
104 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
105 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
106 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
107 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
108 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
109 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
110 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
111 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
112 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
113 * member has been initialized, doesn't do exception handling, and doesn't do
114 * memory allocation. Also doesn't check tag, assumes the caller has checked
115 * it.
117 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
118 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
119 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
120 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
121 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
122 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
123 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
124 void *pvStructInfo, DWORD *pcbStructInfo);
126 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
127 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
128 DWORD *pcbStructInfo)
130 static HCRYPTOIDFUNCSET set = NULL;
131 BOOL ret = FALSE;
132 CryptDecodeObjectFunc pCryptDecodeObject;
133 HCRYPTOIDFUNCADDR hFunc;
135 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
136 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
137 pvStructInfo, pcbStructInfo);
139 if (!pvStructInfo && !pcbStructInfo)
141 SetLastError(ERROR_INVALID_PARAMETER);
142 return FALSE;
145 /* Try registered DLL first.. */
146 if (!set)
147 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
148 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
149 (void **)&pCryptDecodeObject, &hFunc);
150 if (pCryptDecodeObject)
152 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
153 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
154 CryptFreeOIDFunctionAddress(hFunc, 0);
156 else
158 /* If not, use CryptDecodeObjectEx */
159 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
160 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
162 return ret;
165 /* Gets the number of length bytes from the given (leading) length byte */
166 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
168 /* Helper function to get the encoded length of the data starting at pbEncoded,
169 * where pbEncoded[0] is the tag. If the data are too short to contain a
170 * length or if the length is too large for cbEncoded, sets an appropriate
171 * error code and returns FALSE.
173 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
174 DWORD *len)
176 BOOL ret;
178 if (cbEncoded <= 1)
180 SetLastError(CRYPT_E_ASN1_CORRUPT);
181 ret = FALSE;
183 else if (pbEncoded[1] <= 0x7f)
185 if (pbEncoded[1] + 1 > cbEncoded)
187 SetLastError(CRYPT_E_ASN1_EOD);
188 ret = FALSE;
190 else
192 *len = pbEncoded[1];
193 ret = TRUE;
196 else if (pbEncoded[1] == 0x80)
198 FIXME("unimplemented for indefinite-length encoding\n");
199 SetLastError(CRYPT_E_ASN1_CORRUPT);
200 ret = FALSE;
202 else
204 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
206 if (lenLen > sizeof(DWORD) + 1)
208 SetLastError(CRYPT_E_ASN1_LARGE);
209 ret = FALSE;
211 else if (lenLen + 2 > cbEncoded)
213 SetLastError(CRYPT_E_ASN1_CORRUPT);
214 ret = FALSE;
216 else
218 DWORD out = 0;
220 pbEncoded += 2;
221 while (--lenLen)
223 out <<= 8;
224 out |= *pbEncoded++;
226 if (out + lenLen + 1 > cbEncoded)
228 SetLastError(CRYPT_E_ASN1_EOD);
229 ret = FALSE;
231 else
233 *len = out;
234 ret = TRUE;
238 return ret;
241 /* Helper function to check *pcbStructInfo, set it to the required size, and
242 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
243 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
244 * pointer to the newly allocated memory.
246 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
247 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
248 DWORD bytesNeeded)
250 BOOL ret = TRUE;
252 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
254 if (pDecodePara && pDecodePara->pfnAlloc)
255 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
256 else
257 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
258 if (!*(BYTE **)pvStructInfo)
259 ret = FALSE;
260 else
261 *pcbStructInfo = bytesNeeded;
263 else if (*pcbStructInfo < bytesNeeded)
265 *pcbStructInfo = bytesNeeded;
266 SetLastError(ERROR_MORE_DATA);
267 ret = FALSE;
269 return ret;
272 /* tag:
273 * The expected tag of the item. If tag is 0, decodeFunc is called
274 * regardless of the tag value seen.
275 * offset:
276 * A sequence is decoded into a struct. The offset member is the
277 * offset of this item within that struct.
278 * decodeFunc:
279 * The decoder function to use. If this is NULL, then the member isn't
280 * decoded, but minSize space is reserved for it.
281 * minSize:
282 * The minimum amount of space occupied after decoding. You must set this.
283 * optional:
284 * If true, and the tag doesn't match the expected tag for this item,
285 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
286 * filled with 0 for this member.
287 * hasPointer, pointerOffset:
288 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
289 * the offset within the struct of the data pointer (or to the
290 * first data pointer, if more than one exist).
291 * size:
292 * Used by CRYPT_AsnDecodeSequence, not for your use.
294 struct AsnDecodeSequenceItem
296 BYTE tag;
297 DWORD offset;
298 CryptDecodeObjectExFunc decodeFunc;
299 DWORD minSize;
300 BOOL optional;
301 BOOL hasPointer;
302 DWORD pointerOffset;
303 DWORD size;
306 /* Decodes the items in a sequence, where the items are described in items,
307 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
308 * pvStructInfo. nextData is a pointer to the memory location at which the
309 * first decoded item with a dynamic pointer should point.
310 * Upon decoding, *cbDecoded is the total number of bytes decoded.
312 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
313 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
314 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
315 DWORD *cbDecoded)
317 BOOL ret;
318 DWORD i, decoded = 0;
319 const BYTE *ptr = pbEncoded;
321 for (i = 0, ret = TRUE; ret && i < cItem; i++)
323 if (cbEncoded - (ptr - pbEncoded) != 0)
325 DWORD nextItemLen;
327 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
328 &nextItemLen)))
330 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
332 if (ptr[0] == items[i].tag || !items[i].tag)
334 if (nextData && pvStructInfo && items[i].hasPointer)
336 TRACE("Setting next pointer to %p\n",
337 nextData);
338 *(BYTE **)((BYTE *)pvStructInfo +
339 items[i].pointerOffset) = nextData;
341 if (items[i].decodeFunc)
343 if (pvStructInfo)
344 TRACE("decoding item %d\n", i);
345 else
346 TRACE("sizing item %d\n", i);
347 ret = items[i].decodeFunc(dwCertEncodingType,
348 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
349 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
350 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
351 : NULL, &items[i].size);
352 if (ret)
354 if (nextData && items[i].hasPointer &&
355 items[i].size > items[i].minSize)
357 nextData += items[i].size - items[i].minSize;
358 /* align nextData to DWORD boundaries */
359 if (items[i].size % sizeof(DWORD))
360 nextData += sizeof(DWORD) - items[i].size %
361 sizeof(DWORD);
363 /* Account for alignment padding */
364 if (items[i].size % sizeof(DWORD))
365 items[i].size += sizeof(DWORD) -
366 items[i].size % sizeof(DWORD);
367 ptr += 1 + nextItemLenBytes + nextItemLen;
368 decoded += 1 + nextItemLenBytes + nextItemLen;
370 else if (items[i].optional &&
371 GetLastError() == CRYPT_E_ASN1_BADTAG)
373 TRACE("skipping optional item %d\n", i);
374 items[i].size = items[i].minSize;
375 SetLastError(NOERROR);
376 ret = TRUE;
378 else
379 TRACE("item %d failed: %08x\n", i,
380 GetLastError());
382 else
384 ptr += 1 + nextItemLenBytes + nextItemLen;
385 decoded += 1 + nextItemLenBytes + nextItemLen;
386 items[i].size = items[i].minSize;
389 else if (items[i].optional)
391 TRACE("skipping optional item %d\n", i);
392 items[i].size = items[i].minSize;
394 else
396 TRACE("tag %02x doesn't match expected %02x\n",
397 ptr[0], items[i].tag);
398 SetLastError(CRYPT_E_ASN1_BADTAG);
399 ret = FALSE;
403 else if (items[i].optional)
405 TRACE("missing optional item %d, skipping\n", i);
406 items[i].size = items[i].minSize;
408 else
410 TRACE("not enough bytes for item %d, failing\n", i);
411 SetLastError(CRYPT_E_ASN1_CORRUPT);
412 ret = FALSE;
415 if (ret)
416 *cbDecoded = decoded;
417 return ret;
420 /* This decodes an arbitrary sequence into a contiguous block of memory
421 * (basically, a struct.) Each element being decoded is described by a struct
422 * AsnDecodeSequenceItem, see above.
423 * startingPointer is an optional pointer to the first place where dynamic
424 * data will be stored. If you know the starting offset, you may pass it
425 * here. Otherwise, pass NULL, and one will be inferred from the items.
426 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
428 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
429 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
430 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
431 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
433 BOOL ret;
435 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
436 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
437 startingPointer);
439 if (pbEncoded[0] == ASN_SEQUENCE)
441 DWORD dataLen;
443 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
445 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
446 const BYTE *ptr = pbEncoded + 1 + lenBytes;
448 cbEncoded -= 1 + lenBytes;
449 if (cbEncoded < dataLen)
451 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
452 cbEncoded);
453 SetLastError(CRYPT_E_ASN1_CORRUPT);
454 ret = FALSE;
456 else
457 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
458 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
459 if (ret && cbDecoded != dataLen)
461 TRACE("expected %d decoded, got %d, failing\n", dataLen,
462 cbDecoded);
463 SetLastError(CRYPT_E_ASN1_CORRUPT);
464 ret = FALSE;
466 if (ret)
468 DWORD i, bytesNeeded = 0, structSize = 0;
470 for (i = 0; i < cItem; i++)
472 bytesNeeded += items[i].size;
473 structSize += items[i].minSize;
475 if (!pvStructInfo)
476 *pcbStructInfo = bytesNeeded;
477 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
478 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
480 BYTE *nextData;
482 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
483 pvStructInfo = *(BYTE **)pvStructInfo;
484 if (startingPointer)
485 nextData = (BYTE *)startingPointer;
486 else
487 nextData = (BYTE *)pvStructInfo + structSize;
488 memset(pvStructInfo, 0, structSize);
489 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
490 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
491 &cbDecoded);
496 else
498 SetLastError(CRYPT_E_ASN1_BADTAG);
499 ret = FALSE;
501 TRACE("returning %d (%08x)\n", ret, GetLastError());
502 return ret;
505 /* tag:
506 * The expected tag of the entire encoded array (usually a variant
507 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
508 * regardless of the tag seen.
509 * decodeFunc:
510 * used to decode each item in the array
511 * itemSize:
512 * is the minimum size of each decoded item
513 * hasPointer:
514 * indicates whether each item has a dynamic pointer
515 * pointerOffset:
516 * indicates the offset within itemSize at which the pointer exists
518 struct AsnArrayDescriptor
520 BYTE tag;
521 CryptDecodeObjectExFunc decodeFunc;
522 DWORD itemSize;
523 BOOL hasPointer;
524 DWORD pointerOffset;
527 struct AsnArrayItemSize
529 DWORD encodedLen;
530 DWORD size;
533 /* Decodes an array of like types into a struct GenericArray.
534 * The layout and decoding of the array are described by a struct
535 * AsnArrayDescriptor.
537 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
538 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
539 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
540 void *startingPointer)
542 BOOL ret = TRUE;
544 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
545 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
546 startingPointer);
548 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
550 DWORD dataLen;
552 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
554 DWORD bytesNeeded, cItems = 0;
555 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
556 /* There can be arbitrarily many items, but there is often only one.
558 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
560 bytesNeeded = sizeof(struct GenericArray);
561 if (dataLen)
563 const BYTE *ptr;
565 for (ptr = pbEncoded + 1 + lenBytes; ret &&
566 ptr - pbEncoded - 1 - lenBytes < dataLen; )
568 DWORD itemLenBytes, itemDataLen, size = 0;
570 itemLenBytes = GET_LEN_BYTES(ptr[1]);
571 /* Each item decoded may not tolerate extraneous bytes, so
572 * get the length of the next element and pass it directly.
574 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
575 &itemDataLen);
576 if (ret)
577 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
578 1 + itemLenBytes + itemDataLen,
579 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
580 &size);
581 if (ret)
583 DWORD nextLen;
585 cItems++;
586 if (itemSizes != &itemSize)
587 itemSizes = CryptMemRealloc(itemSizes,
588 cItems * sizeof(struct AsnArrayItemSize));
589 else
591 itemSizes =
592 CryptMemAlloc(
593 cItems * sizeof(struct AsnArrayItemSize));
594 if (itemSizes)
595 memcpy(itemSizes, &itemSize, sizeof(itemSize));
597 if (itemSizes)
599 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
600 + itemDataLen;
601 itemSizes[cItems - 1].size = size;
602 bytesNeeded += size;
603 ret = CRYPT_GetLen(ptr,
604 cbEncoded - (ptr - pbEncoded), &nextLen);
605 if (ret)
606 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
608 else
609 ret = FALSE;
613 if (ret)
615 if (!pvStructInfo)
616 *pcbStructInfo = bytesNeeded;
617 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
618 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
620 DWORD i;
621 BYTE *nextData;
622 const BYTE *ptr;
623 struct GenericArray *array;
625 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
626 pvStructInfo = *(BYTE **)pvStructInfo;
627 array = (struct GenericArray *)pvStructInfo;
628 array->cItems = cItems;
629 if (startingPointer)
630 array->rgItems = startingPointer;
631 else
632 array->rgItems = (BYTE *)array +
633 sizeof(struct GenericArray);
634 nextData = (BYTE *)array->rgItems +
635 array->cItems * arrayDesc->itemSize;
636 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
637 i < cItems && ptr - pbEncoded - 1 - lenBytes <
638 dataLen; i++)
640 if (arrayDesc->hasPointer)
641 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
642 + arrayDesc->pointerOffset) = nextData;
643 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
644 itemSizes[i].encodedLen,
645 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
646 array->rgItems + i * arrayDesc->itemSize,
647 &itemSizes[i].size);
648 if (ret)
650 DWORD nextLen;
652 nextData += itemSizes[i].size - arrayDesc->itemSize;
653 ret = CRYPT_GetLen(ptr,
654 cbEncoded - (ptr - pbEncoded), &nextLen);
655 if (ret)
656 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
661 if (itemSizes != &itemSize)
662 CryptMemFree(itemSizes);
665 else
667 SetLastError(CRYPT_E_ASN1_BADTAG);
668 ret = FALSE;
670 return ret;
673 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
674 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
675 * to CRYPT_E_ASN1_CORRUPT.
676 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
677 * set!
679 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
680 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
681 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
683 BOOL ret;
684 DWORD dataLen;
686 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
688 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
689 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
691 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
692 bytesNeeded += 1 + lenBytes + dataLen;
694 if (!pvStructInfo)
695 *pcbStructInfo = bytesNeeded;
696 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
697 pvStructInfo, pcbStructInfo, bytesNeeded)))
699 CRYPT_DER_BLOB *blob;
701 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
702 pvStructInfo = *(BYTE **)pvStructInfo;
703 blob = (CRYPT_DER_BLOB *)pvStructInfo;
704 blob->cbData = 1 + lenBytes + dataLen;
705 if (blob->cbData)
707 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
708 blob->pbData = (BYTE *)pbEncoded;
709 else
711 assert(blob->pbData);
712 memcpy(blob->pbData, pbEncoded, blob->cbData);
715 else
717 SetLastError(CRYPT_E_ASN1_CORRUPT);
718 ret = FALSE;
722 return ret;
725 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
726 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
727 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
728 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
730 BOOL ret;
732 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
733 pDecodePara, pvStructInfo, *pcbStructInfo);
735 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
736 * place.
738 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
739 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
740 pvStructInfo, pcbStructInfo);
741 if (ret && pvStructInfo)
743 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
745 if (blob->cbData)
747 DWORD i;
748 BYTE temp;
750 for (i = 0; i < blob->cbData / 2; i++)
752 temp = blob->pbData[i];
753 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
754 blob->pbData[blob->cbData - i - 1] = temp;
758 TRACE("returning %d (%08x)\n", ret, GetLastError());
759 return ret;
762 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
763 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
764 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
766 BOOL ret = TRUE;
768 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
769 pDecodePara, pvStructInfo, *pcbStructInfo);
771 __TRY
773 struct AsnDecodeSequenceItem items[] = {
774 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
775 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
776 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
777 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
778 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
779 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
780 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
781 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
782 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
783 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
786 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
787 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
788 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
789 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
790 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
792 __EXCEPT_PAGE_FAULT
794 SetLastError(STATUS_ACCESS_VIOLATION);
795 ret = FALSE;
797 __ENDTRY
799 TRACE("Returning %d (%08x)\n", ret, GetLastError());
800 return ret;
803 /* Internal function */
804 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
805 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
806 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
808 BOOL ret;
809 DWORD dataLen;
811 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
813 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
815 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
816 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
817 pvStructInfo, pcbStructInfo);
819 return ret;
822 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
823 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
824 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
826 BOOL ret;
828 struct AsnDecodeSequenceItem items[] = {
829 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
830 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
831 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
832 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
835 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
836 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
837 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
838 return ret;
841 /* Internal function */
842 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
843 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
844 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
846 BOOL ret;
847 DWORD dataLen;
849 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
851 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
853 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
854 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
855 pDecodePara, pvStructInfo, pcbStructInfo);
857 return ret;
860 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
861 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
862 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
864 BOOL ret = TRUE;
865 struct AsnDecodeSequenceItem items[] = {
866 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
867 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
868 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
869 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
870 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
871 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
872 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
873 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
874 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
875 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
876 Issuer.pbData) },
877 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
878 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
879 FALSE, 0 },
880 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
881 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
882 Subject.pbData) },
883 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
884 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
885 FALSE, TRUE, offsetof(CERT_INFO,
886 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
887 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
888 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
889 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
890 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
891 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
892 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
893 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
894 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
895 offsetof(CERT_INFO, rgExtension), 0 },
898 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
899 pDecodePara, pvStructInfo, *pcbStructInfo);
901 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
902 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
903 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
904 if (ret && pvStructInfo)
906 CERT_INFO *info;
908 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
909 info = *(CERT_INFO **)pvStructInfo;
910 else
911 info = (CERT_INFO *)pvStructInfo;
912 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
913 !info->Subject.cbData)
915 SetLastError(CRYPT_E_ASN1_CORRUPT);
916 /* Don't need to deallocate, because it should have failed on the
917 * first pass (and no memory was allocated.)
919 ret = FALSE;
923 TRACE("Returning %d (%08x)\n", ret, GetLastError());
924 return ret;
927 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
928 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
929 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
931 BOOL ret = TRUE;
933 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
934 pDecodePara, pvStructInfo, *pcbStructInfo);
936 __TRY
938 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
939 DWORD size = 0;
941 /* First try to decode it as a signed cert. */
942 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
943 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
944 (BYTE *)&signedCert, &size);
945 if (ret)
947 size = 0;
948 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
949 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
950 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
951 pcbStructInfo);
952 LocalFree(signedCert);
954 /* Failing that, try it as an unsigned cert */
955 if (!ret)
957 size = 0;
958 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
959 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
960 pDecodePara, pvStructInfo, pcbStructInfo);
963 __EXCEPT_PAGE_FAULT
965 SetLastError(STATUS_ACCESS_VIOLATION);
966 ret = FALSE;
968 __ENDTRY
970 TRACE("Returning %d (%08x)\n", ret, GetLastError());
971 return ret;
974 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
975 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
976 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
978 BOOL ret;
979 struct AsnDecodeSequenceItem items[] = {
980 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
981 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
982 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
983 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
984 sizeof(FILETIME), FALSE, FALSE, 0 },
985 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
986 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
987 offsetof(CRL_ENTRY, rgExtension), 0 },
989 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
991 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
992 *pcbStructInfo);
994 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
995 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
996 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
997 return ret;
1000 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1001 * been set prior to calling.
1003 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
1004 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1005 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1007 BOOL ret;
1008 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1009 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1010 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1011 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1013 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1014 pDecodePara, pvStructInfo, *pcbStructInfo);
1016 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1017 pDecodePara, pvStructInfo, pcbStructInfo,
1018 entries ? entries->rgItems : NULL);
1019 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1020 return ret;
1023 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1024 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1025 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1027 struct AsnDecodeSequenceItem items[] = {
1028 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1029 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1030 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1031 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1032 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1033 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1034 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1035 Issuer.pbData) },
1036 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
1037 sizeof(FILETIME), FALSE, FALSE, 0 },
1038 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
1039 sizeof(FILETIME), TRUE, FALSE, 0 },
1040 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1041 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1042 offsetof(CRL_INFO, rgCRLEntry), 0 },
1043 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1044 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1045 offsetof(CRL_INFO, rgExtension), 0 },
1047 BOOL ret = TRUE;
1049 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1050 pDecodePara, pvStructInfo, *pcbStructInfo);
1052 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1053 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1054 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1056 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1057 return ret;
1060 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1061 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1062 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1064 BOOL ret = TRUE;
1066 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1067 pDecodePara, pvStructInfo, *pcbStructInfo);
1069 __TRY
1071 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1072 DWORD size = 0;
1074 /* First try to decode it as a signed crl. */
1075 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1076 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1077 (BYTE *)&signedCrl, &size);
1078 if (ret)
1080 size = 0;
1081 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1082 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1083 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1084 pvStructInfo, pcbStructInfo);
1085 LocalFree(signedCrl);
1087 /* Failing that, try it as an unsigned crl */
1088 if (!ret)
1090 size = 0;
1091 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1092 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1093 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1096 __EXCEPT_PAGE_FAULT
1098 SetLastError(STATUS_ACCESS_VIOLATION);
1099 ret = FALSE;
1101 __ENDTRY
1103 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1104 return ret;
1107 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1108 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1109 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1111 BOOL ret = TRUE;
1113 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1114 pDecodePara, pvStructInfo, *pcbStructInfo);
1116 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1118 DWORD dataLen;
1120 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1122 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1123 DWORD bytesNeeded = sizeof(LPSTR);
1125 if (dataLen)
1127 /* The largest possible string for the first two components
1128 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1130 char firstTwo[6];
1131 const BYTE *ptr;
1133 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1134 pbEncoded[1 + lenBytes] / 40,
1135 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1136 * 40);
1137 bytesNeeded += strlen(firstTwo) + 1;
1138 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1139 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1141 /* large enough for ".4000000" */
1142 char str[9];
1143 int val = 0;
1145 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1146 (*ptr & 0x80))
1148 val <<= 7;
1149 val |= *ptr & 0x7f;
1150 ptr++;
1152 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1153 (*ptr & 0x80))
1155 SetLastError(CRYPT_E_ASN1_CORRUPT);
1156 ret = FALSE;
1158 else
1160 val <<= 7;
1161 val |= *ptr++;
1162 snprintf(str, sizeof(str), ".%d", val);
1163 bytesNeeded += strlen(str);
1167 if (!pvStructInfo)
1168 *pcbStructInfo = bytesNeeded;
1169 else if (*pcbStructInfo < bytesNeeded)
1171 *pcbStructInfo = bytesNeeded;
1172 SetLastError(ERROR_MORE_DATA);
1173 ret = FALSE;
1175 else
1177 if (dataLen)
1179 const BYTE *ptr;
1180 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1182 *pszObjId = 0;
1183 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1184 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1185 40) * 40);
1186 pszObjId += strlen(pszObjId);
1187 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1188 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1190 int val = 0;
1192 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1193 (*ptr & 0x80))
1195 val <<= 7;
1196 val |= *ptr & 0x7f;
1197 ptr++;
1199 val <<= 7;
1200 val |= *ptr++;
1201 sprintf(pszObjId, ".%d", val);
1202 pszObjId += strlen(pszObjId);
1205 else
1206 *(LPSTR *)pvStructInfo = NULL;
1207 *pcbStructInfo = bytesNeeded;
1211 return ret;
1214 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1215 * ahead of time!
1217 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1218 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1219 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1221 struct AsnDecodeSequenceItem items[] = {
1222 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1223 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1224 offsetof(CERT_EXTENSION, pszObjId), 0 },
1225 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1226 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1227 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1228 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1229 offsetof(CERT_EXTENSION, Value.pbData) },
1231 BOOL ret = TRUE;
1232 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1234 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1235 *pcbStructInfo);
1237 if (ext)
1238 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1239 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1240 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1241 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1242 if (ext)
1243 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1244 debugstr_a(ext->pszObjId));
1245 TRACE("returning %d (%08x)\n", ret, GetLastError());
1246 return ret;
1249 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(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;
1254 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1255 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1256 offsetof(CERT_EXTENSION, pszObjId) };
1257 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1259 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1260 pDecodePara, pvStructInfo, *pcbStructInfo);
1262 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1263 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1264 return ret;
1267 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1268 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1269 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1271 BOOL ret = TRUE;
1273 __TRY
1275 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1276 lpszStructType, pbEncoded, cbEncoded,
1277 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1278 if (ret && pvStructInfo)
1280 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1281 pcbStructInfo, *pcbStructInfo);
1282 if (ret)
1284 CERT_EXTENSIONS *exts;
1286 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1287 pvStructInfo = *(BYTE **)pvStructInfo;
1288 exts = (CERT_EXTENSIONS *)pvStructInfo;
1289 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1290 sizeof(CERT_EXTENSIONS));
1291 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1292 lpszStructType, pbEncoded, cbEncoded,
1293 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1294 pcbStructInfo);
1298 __EXCEPT_PAGE_FAULT
1300 SetLastError(STATUS_ACCESS_VIOLATION);
1301 ret = FALSE;
1303 __ENDTRY
1304 return ret;
1307 /* Warning: this assumes the address of value->Value.pbData is already set, in
1308 * order to avoid overwriting memory. (In some cases, it may change it, if it
1309 * doesn't copy anything to memory.) Be sure to set it correctly!
1311 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1312 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1313 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1315 BOOL ret = TRUE;
1316 DWORD dataLen;
1317 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1319 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1321 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1322 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1324 switch (pbEncoded[0])
1326 case ASN_OCTETSTRING:
1327 valueType = CERT_RDN_OCTET_STRING;
1328 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1329 bytesNeeded += dataLen;
1330 break;
1331 case ASN_NUMERICSTRING:
1332 valueType = CERT_RDN_NUMERIC_STRING;
1333 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1334 bytesNeeded += dataLen;
1335 break;
1336 case ASN_PRINTABLESTRING:
1337 valueType = CERT_RDN_PRINTABLE_STRING;
1338 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1339 bytesNeeded += dataLen;
1340 break;
1341 case ASN_IA5STRING:
1342 valueType = CERT_RDN_IA5_STRING;
1343 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1344 bytesNeeded += dataLen;
1345 break;
1346 case ASN_T61STRING:
1347 valueType = CERT_RDN_T61_STRING;
1348 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1349 bytesNeeded += dataLen;
1350 break;
1351 case ASN_VIDEOTEXSTRING:
1352 valueType = CERT_RDN_VIDEOTEX_STRING;
1353 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1354 bytesNeeded += dataLen;
1355 break;
1356 case ASN_GRAPHICSTRING:
1357 valueType = CERT_RDN_GRAPHIC_STRING;
1358 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1359 bytesNeeded += dataLen;
1360 break;
1361 case ASN_VISIBLESTRING:
1362 valueType = CERT_RDN_VISIBLE_STRING;
1363 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1364 bytesNeeded += dataLen;
1365 break;
1366 case ASN_GENERALSTRING:
1367 valueType = CERT_RDN_GENERAL_STRING;
1368 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1369 bytesNeeded += dataLen;
1370 break;
1371 case ASN_UNIVERSALSTRING:
1372 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1373 SetLastError(CRYPT_E_ASN1_BADTAG);
1374 return FALSE;
1375 case ASN_BMPSTRING:
1376 valueType = CERT_RDN_BMP_STRING;
1377 bytesNeeded += dataLen;
1378 break;
1379 case ASN_UTF8STRING:
1380 valueType = CERT_RDN_UTF8_STRING;
1381 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1382 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1383 break;
1384 default:
1385 SetLastError(CRYPT_E_ASN1_BADTAG);
1386 return FALSE;
1389 if (!value)
1390 *pcbStructInfo = bytesNeeded;
1391 else if (*pcbStructInfo < bytesNeeded)
1393 *pcbStructInfo = bytesNeeded;
1394 SetLastError(ERROR_MORE_DATA);
1395 ret = FALSE;
1397 else
1399 *pcbStructInfo = bytesNeeded;
1400 value->dwValueType = valueType;
1401 if (dataLen)
1403 DWORD i;
1405 assert(value->Value.pbData);
1406 switch (pbEncoded[0])
1408 case ASN_OCTETSTRING:
1409 case ASN_NUMERICSTRING:
1410 case ASN_PRINTABLESTRING:
1411 case ASN_IA5STRING:
1412 case ASN_T61STRING:
1413 case ASN_VIDEOTEXSTRING:
1414 case ASN_GRAPHICSTRING:
1415 case ASN_VISIBLESTRING:
1416 case ASN_GENERALSTRING:
1417 value->Value.cbData = dataLen;
1418 if (dataLen)
1420 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1421 memcpy(value->Value.pbData,
1422 pbEncoded + 1 + lenBytes, dataLen);
1423 else
1424 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1425 lenBytes;
1427 break;
1428 case ASN_BMPSTRING:
1430 LPWSTR str = (LPWSTR)value->Value.pbData;
1432 value->Value.cbData = dataLen;
1433 for (i = 0; i < dataLen / 2; i++)
1434 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1435 pbEncoded[1 + lenBytes + 2 * i + 1];
1436 break;
1438 case ASN_UTF8STRING:
1440 LPWSTR str = (LPWSTR)value->Value.pbData;
1442 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1443 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1444 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1445 break;
1449 else
1451 value->Value.cbData = 0;
1452 value->Value.pbData = NULL;
1456 return ret;
1459 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1460 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1461 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1463 BOOL ret = TRUE;
1465 __TRY
1467 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1468 lpszStructType, pbEncoded, cbEncoded,
1469 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1470 if (ret && pvStructInfo)
1472 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1473 pcbStructInfo, *pcbStructInfo);
1474 if (ret)
1476 CERT_NAME_VALUE *value;
1478 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1479 pvStructInfo = *(BYTE **)pvStructInfo;
1480 value = (CERT_NAME_VALUE *)pvStructInfo;
1481 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1482 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1483 lpszStructType, pbEncoded, cbEncoded,
1484 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1485 pcbStructInfo);
1489 __EXCEPT_PAGE_FAULT
1491 SetLastError(STATUS_ACCESS_VIOLATION);
1492 ret = FALSE;
1494 __ENDTRY
1495 return ret;
1498 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1499 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1500 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1501 void *pvStructInfo, DWORD *pcbStructInfo)
1503 BOOL ret = TRUE;
1504 DWORD dataLen;
1505 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1507 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1509 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1510 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1512 switch (pbEncoded[0])
1514 case ASN_NUMERICSTRING:
1515 valueType = CERT_RDN_NUMERIC_STRING;
1516 bytesNeeded += dataLen * 2;
1517 break;
1518 case ASN_PRINTABLESTRING:
1519 valueType = CERT_RDN_PRINTABLE_STRING;
1520 bytesNeeded += dataLen * 2;
1521 break;
1522 case ASN_IA5STRING:
1523 valueType = CERT_RDN_IA5_STRING;
1524 bytesNeeded += dataLen * 2;
1525 break;
1526 case ASN_T61STRING:
1527 valueType = CERT_RDN_T61_STRING;
1528 bytesNeeded += dataLen * 2;
1529 break;
1530 case ASN_VIDEOTEXSTRING:
1531 valueType = CERT_RDN_VIDEOTEX_STRING;
1532 bytesNeeded += dataLen * 2;
1533 break;
1534 case ASN_GRAPHICSTRING:
1535 valueType = CERT_RDN_GRAPHIC_STRING;
1536 bytesNeeded += dataLen * 2;
1537 break;
1538 case ASN_VISIBLESTRING:
1539 valueType = CERT_RDN_VISIBLE_STRING;
1540 bytesNeeded += dataLen * 2;
1541 break;
1542 case ASN_GENERALSTRING:
1543 valueType = CERT_RDN_GENERAL_STRING;
1544 bytesNeeded += dataLen * 2;
1545 break;
1546 case ASN_UNIVERSALSTRING:
1547 valueType = CERT_RDN_UNIVERSAL_STRING;
1548 bytesNeeded += dataLen / 2;
1549 break;
1550 case ASN_BMPSTRING:
1551 valueType = CERT_RDN_BMP_STRING;
1552 bytesNeeded += dataLen;
1553 break;
1554 case ASN_UTF8STRING:
1555 valueType = CERT_RDN_UTF8_STRING;
1556 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1557 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1558 break;
1559 default:
1560 SetLastError(CRYPT_E_ASN1_BADTAG);
1561 return FALSE;
1564 if (!value)
1565 *pcbStructInfo = bytesNeeded;
1566 else if (*pcbStructInfo < bytesNeeded)
1568 *pcbStructInfo = bytesNeeded;
1569 SetLastError(ERROR_MORE_DATA);
1570 ret = FALSE;
1572 else
1574 *pcbStructInfo = bytesNeeded;
1575 value->dwValueType = valueType;
1576 if (dataLen)
1578 DWORD i;
1579 LPWSTR str = (LPWSTR)value->Value.pbData;
1581 assert(value->Value.pbData);
1582 switch (pbEncoded[0])
1584 case ASN_NUMERICSTRING:
1585 case ASN_PRINTABLESTRING:
1586 case ASN_IA5STRING:
1587 case ASN_T61STRING:
1588 case ASN_VIDEOTEXSTRING:
1589 case ASN_GRAPHICSTRING:
1590 case ASN_VISIBLESTRING:
1591 case ASN_GENERALSTRING:
1592 value->Value.cbData = dataLen * 2;
1593 for (i = 0; i < dataLen; i++)
1594 str[i] = pbEncoded[1 + lenBytes + i];
1595 break;
1596 case ASN_UNIVERSALSTRING:
1597 value->Value.cbData = dataLen / 2;
1598 for (i = 0; i < dataLen / 4; i++)
1599 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1600 | pbEncoded[1 + lenBytes + 2 * i + 3];
1601 break;
1602 case ASN_BMPSTRING:
1603 value->Value.cbData = dataLen;
1604 for (i = 0; i < dataLen / 2; i++)
1605 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1606 pbEncoded[1 + lenBytes + 2 * i + 1];
1607 break;
1608 case ASN_UTF8STRING:
1609 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1610 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1611 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1612 break;
1615 else
1617 value->Value.cbData = 0;
1618 value->Value.pbData = NULL;
1622 return ret;
1625 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1626 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1627 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1629 BOOL ret = TRUE;
1631 __TRY
1633 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1634 lpszStructType, pbEncoded, cbEncoded,
1635 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1636 if (ret && pvStructInfo)
1638 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1639 pcbStructInfo, *pcbStructInfo);
1640 if (ret)
1642 CERT_NAME_VALUE *value;
1644 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1645 pvStructInfo = *(BYTE **)pvStructInfo;
1646 value = (CERT_NAME_VALUE *)pvStructInfo;
1647 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1648 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1649 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1650 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1651 pcbStructInfo);
1655 __EXCEPT_PAGE_FAULT
1657 SetLastError(STATUS_ACCESS_VIOLATION);
1658 ret = FALSE;
1660 __ENDTRY
1661 return ret;
1664 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1665 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1666 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1668 BOOL ret;
1669 struct AsnDecodeSequenceItem items[] = {
1670 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1671 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1672 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1673 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1674 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1675 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1677 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1679 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1680 pvStructInfo, *pcbStructInfo);
1682 if (attr)
1683 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1684 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1685 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1686 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1687 if (attr)
1689 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1690 debugstr_a(attr->pszObjId));
1691 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1693 TRACE("returning %d (%08x)\n", ret, GetLastError());
1694 return ret;
1697 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1698 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1699 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1701 BOOL ret = TRUE;
1702 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1703 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1704 offsetof(CERT_RDN_ATTR, pszObjId) };
1705 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1707 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1708 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1709 return ret;
1712 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1713 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1714 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1716 BOOL ret = TRUE;
1718 __TRY
1720 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1721 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1722 offsetof(CERT_RDN, rgRDNAttr) };
1724 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1725 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1727 __EXCEPT_PAGE_FAULT
1729 SetLastError(STATUS_ACCESS_VIOLATION);
1730 ret = FALSE;
1732 __ENDTRY
1733 return ret;
1736 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
1737 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1738 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1740 BOOL ret;
1741 struct AsnDecodeSequenceItem items[] = {
1742 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1743 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1744 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1745 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1746 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1747 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1749 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1751 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1752 pvStructInfo, *pcbStructInfo);
1754 if (attr)
1755 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1756 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1757 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1758 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1759 if (attr)
1761 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1762 debugstr_a(attr->pszObjId));
1763 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1765 TRACE("returning %d (%08x)\n", ret, GetLastError());
1766 return ret;
1769 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
1770 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1771 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1773 BOOL ret = TRUE;
1774 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1775 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1776 offsetof(CERT_RDN_ATTR, pszObjId) };
1777 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1779 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1780 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1781 return ret;
1784 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1785 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1786 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1788 BOOL ret = TRUE;
1790 __TRY
1792 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1793 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1794 offsetof(CERT_RDN, rgRDNAttr) };
1796 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1797 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1799 __EXCEPT_PAGE_FAULT
1801 SetLastError(STATUS_ACCESS_VIOLATION);
1802 ret = FALSE;
1804 __ENDTRY
1805 return ret;
1808 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1809 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1810 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1812 BOOL ret = TRUE;
1813 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1815 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1816 pDecodePara, pvStructInfo, *pcbStructInfo);
1818 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1819 bytesNeeded += cbEncoded;
1820 if (!pvStructInfo)
1821 *pcbStructInfo = bytesNeeded;
1822 else if (*pcbStructInfo < bytesNeeded)
1824 SetLastError(ERROR_MORE_DATA);
1825 *pcbStructInfo = bytesNeeded;
1826 ret = FALSE;
1828 else
1830 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1832 *pcbStructInfo = bytesNeeded;
1833 blob->cbData = cbEncoded;
1834 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1835 blob->pbData = (LPBYTE)pbEncoded;
1836 else
1838 assert(blob->pbData);
1839 memcpy(blob->pbData, pbEncoded, blob->cbData);
1842 return ret;
1845 static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType,
1846 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1847 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1849 BOOL ret;
1850 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
1851 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1852 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1854 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1855 pDecodePara, pvStructInfo, *pcbStructInfo);
1857 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1858 pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
1859 return ret;
1862 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1863 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1864 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1866 BOOL ret = FALSE;
1868 __TRY
1870 struct AsnDecodeSequenceItem items[] = {
1871 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1872 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1873 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1874 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1875 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1876 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1878 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1880 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1881 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1882 pDecodePara, pvStructInfo, pcbStructInfo, attr ? attr->pszObjId :
1883 NULL);
1885 __EXCEPT_PAGE_FAULT
1887 SetLastError(STATUS_ACCESS_VIOLATION);
1889 __ENDTRY
1890 TRACE("returning %d\n", ret);
1891 return ret;
1894 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal(
1895 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1896 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1897 void *pvStructInfo, DWORD *pcbStructInfo)
1899 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1900 CRYPT_AsnDecodePKCSAttribute, sizeof(CRYPT_ATTRIBUTE), TRUE,
1901 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
1902 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1903 BOOL ret;
1905 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1906 pDecodePara, pvStructInfo, pcbStructInfo, attrs ? attrs->rgAttr :
1907 NULL);
1908 return ret;
1911 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
1912 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1913 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1915 BOOL ret = FALSE;
1917 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1918 pDecodePara, pvStructInfo, *pcbStructInfo);
1920 __TRY
1922 DWORD bytesNeeded;
1924 if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1925 lpszStructType, pbEncoded, cbEncoded,
1926 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1928 if (!pvStructInfo)
1929 *pcbStructInfo = bytesNeeded;
1930 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1931 pvStructInfo, pcbStructInfo, bytesNeeded)))
1933 PCRYPT_ATTRIBUTES attrs;
1935 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1936 pvStructInfo = *(BYTE **)pvStructInfo;
1937 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1938 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
1939 sizeof(CRYPT_ATTRIBUTES));
1940 ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1941 lpszStructType, pbEncoded, cbEncoded,
1942 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1943 &bytesNeeded);
1947 __EXCEPT_PAGE_FAULT
1949 SetLastError(STATUS_ACCESS_VIOLATION);
1951 __ENDTRY
1952 TRACE("returning %d\n", ret);
1953 return ret;
1956 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1957 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1958 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1960 CRYPT_ALGORITHM_IDENTIFIER *algo =
1961 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1962 BOOL ret = TRUE;
1963 struct AsnDecodeSequenceItem items[] = {
1964 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1965 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1966 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1967 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1968 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1969 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1972 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1973 pDecodePara, pvStructInfo, *pcbStructInfo);
1975 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1976 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1977 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1978 if (ret && pvStructInfo)
1980 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1981 debugstr_a(algo->pszObjId));
1983 return ret;
1986 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1987 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1988 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1990 BOOL ret = TRUE;
1991 struct AsnDecodeSequenceItem items[] = {
1992 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1993 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1994 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1995 Algorithm.pszObjId) },
1996 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1997 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1998 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2000 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2002 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2003 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2004 pDecodePara, pvStructInfo, pcbStructInfo, info ?
2005 info->Algorithm.Parameters.pbData : NULL);
2006 return ret;
2009 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2010 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2011 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2013 BOOL ret = TRUE;
2015 __TRY
2017 DWORD bytesNeeded;
2019 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2020 lpszStructType, pbEncoded, cbEncoded,
2021 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2023 if (!pvStructInfo)
2024 *pcbStructInfo = bytesNeeded;
2025 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2026 pvStructInfo, pcbStructInfo, bytesNeeded)))
2028 PCERT_PUBLIC_KEY_INFO info;
2030 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2031 pvStructInfo = *(BYTE **)pvStructInfo;
2032 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2033 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2034 sizeof(CERT_PUBLIC_KEY_INFO);
2035 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2036 lpszStructType, pbEncoded, cbEncoded,
2037 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2038 &bytesNeeded);
2042 __EXCEPT_PAGE_FAULT
2044 SetLastError(STATUS_ACCESS_VIOLATION);
2045 ret = FALSE;
2047 __ENDTRY
2048 return ret;
2051 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2052 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2053 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2055 BOOL ret;
2057 if (cbEncoded < 3)
2059 SetLastError(CRYPT_E_ASN1_CORRUPT);
2060 return FALSE;
2062 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2064 SetLastError(CRYPT_E_ASN1_CORRUPT);
2065 return FALSE;
2067 if (pbEncoded[1] > 1)
2069 SetLastError(CRYPT_E_ASN1_CORRUPT);
2070 return FALSE;
2072 if (!pvStructInfo)
2074 *pcbStructInfo = sizeof(BOOL);
2075 ret = TRUE;
2077 else if (*pcbStructInfo < sizeof(BOOL))
2079 *pcbStructInfo = sizeof(BOOL);
2080 SetLastError(ERROR_MORE_DATA);
2081 ret = FALSE;
2083 else
2085 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2086 ret = TRUE;
2088 TRACE("returning %d (%08x)\n", ret, GetLastError());
2089 return ret;
2092 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
2093 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2094 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2096 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2097 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2098 BOOL ret;
2100 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2101 pDecodePara, pvStructInfo, *pcbStructInfo);
2103 if (cbEncoded < 2)
2105 SetLastError(CRYPT_E_ASN1_CORRUPT);
2106 return FALSE;
2108 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
2110 SetLastError(CRYPT_E_ASN1_BADTAG);
2111 return FALSE;
2113 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2114 if (1 + lenBytes > cbEncoded)
2116 SetLastError(CRYPT_E_ASN1_CORRUPT);
2117 return FALSE;
2119 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2121 switch (pbEncoded[0] & ASN_TYPE_MASK)
2123 case 1: /* rfc822Name */
2124 case 2: /* dNSName */
2125 case 6: /* uniformResourceIdentifier */
2126 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2127 break;
2128 case 7: /* iPAddress */
2129 bytesNeeded += dataLen;
2130 break;
2131 case 8: /* registeredID */
2132 /* FIXME: decode as OID */
2133 case 0: /* otherName */
2134 case 4: /* directoryName */
2135 FIXME("stub\n");
2136 SetLastError(CRYPT_E_ASN1_BADTAG);
2137 ret = FALSE;
2138 break;
2139 case 3: /* x400Address, unimplemented */
2140 case 5: /* ediPartyName, unimplemented */
2141 SetLastError(CRYPT_E_ASN1_BADTAG);
2142 ret = FALSE;
2143 break;
2144 default:
2145 SetLastError(CRYPT_E_ASN1_CORRUPT);
2146 ret = FALSE;
2148 if (ret)
2150 if (!entry)
2151 *pcbStructInfo = bytesNeeded;
2152 else if (*pcbStructInfo < bytesNeeded)
2154 *pcbStructInfo = bytesNeeded;
2155 SetLastError(ERROR_MORE_DATA);
2156 ret = FALSE;
2158 else
2160 *pcbStructInfo = bytesNeeded;
2161 /* MS used values one greater than the asn1 ones.. sigh */
2162 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2163 switch (pbEncoded[0] & ASN_TYPE_MASK)
2165 case 1: /* rfc822Name */
2166 case 2: /* dNSName */
2167 case 6: /* uniformResourceIdentifier */
2169 DWORD i;
2171 for (i = 0; i < dataLen; i++)
2172 entry->u.pwszURL[i] =
2173 (WCHAR)pbEncoded[1 + lenBytes + i];
2174 entry->u.pwszURL[i] = 0;
2175 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2176 debugstr_w(entry->u.pwszURL));
2177 break;
2179 case 7: /* iPAddress */
2180 /* The next data pointer is in the pwszURL spot, that is,
2181 * the first 4 bytes. Need to move it to the next spot.
2183 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2184 entry->u.IPAddress.cbData = dataLen;
2185 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2186 dataLen);
2187 break;
2192 return ret;
2195 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2196 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2197 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2199 BOOL ret = TRUE;
2200 struct AsnArrayDescriptor arrayDesc = { 0,
2201 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2202 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2203 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2205 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2206 pDecodePara, pvStructInfo, *pcbStructInfo);
2208 if (info)
2209 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2210 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2211 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2212 return ret;
2215 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2216 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2217 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2219 BOOL ret;
2221 __TRY
2223 struct AsnDecodeSequenceItem items[] = {
2224 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2225 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2226 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2227 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2228 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2229 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2230 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2231 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2232 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2233 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2234 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2237 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2238 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2239 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2241 __EXCEPT_PAGE_FAULT
2243 SetLastError(STATUS_ACCESS_VIOLATION);
2244 ret = FALSE;
2246 __ENDTRY
2247 return ret;
2250 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2251 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2252 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2254 BOOL ret;
2256 __TRY
2258 struct AsnDecodeSequenceItem items[] = {
2259 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2260 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2261 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2262 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2263 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2264 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2265 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2266 AuthorityCertIssuer.rgAltEntry), 0 },
2267 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2268 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2269 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2270 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2271 AuthorityCertSerialNumber.pbData), 0 },
2274 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2275 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2276 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2278 __EXCEPT_PAGE_FAULT
2280 SetLastError(STATUS_ACCESS_VIOLATION);
2281 ret = FALSE;
2283 __ENDTRY
2284 return ret;
2287 static BOOL WINAPI CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType,
2288 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2289 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2291 BOOL ret;
2292 DWORD dataLen;
2294 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2295 pDecodePara, pvStructInfo, *pcbStructInfo);
2297 /* The caller has already checked the tag, no need to check it again.
2298 * Check the outer length is valid by calling CRYPT_GetLen:
2300 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2302 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2303 DWORD innerLen;
2305 pbEncoded += 1 + lenBytes;
2306 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2307 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2309 ret = CRYPT_AsnDecodeCopyBytes(dwCertEncodingType, NULL,
2310 pbEncoded, dataLen, dwFlags, pDecodePara, pvStructInfo,
2311 pcbStructInfo);
2314 return ret;
2317 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfoInternal(
2318 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2319 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2320 void *pvStructInfo, DWORD *pcbStructInfo)
2322 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2323 struct AsnDecodeSequenceItem items[] = {
2324 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2325 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
2326 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2327 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2328 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2329 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2330 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2333 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2334 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2335 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->pszObjId : NULL);
2338 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2339 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2340 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2342 BOOL ret = FALSE;
2344 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2345 pDecodePara, pvStructInfo, *pcbStructInfo);
2347 __TRY
2349 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2350 lpszStructType, pbEncoded, cbEncoded,
2351 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
2352 if (ret && pvStructInfo)
2354 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2355 pcbStructInfo, *pcbStructInfo);
2356 if (ret)
2358 CRYPT_CONTENT_INFO *info;
2360 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2361 pvStructInfo = *(BYTE **)pvStructInfo;
2362 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2363 info->pszObjId = (LPSTR)((BYTE *)info +
2364 sizeof(CRYPT_CONTENT_INFO));
2365 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2366 lpszStructType, pbEncoded, cbEncoded,
2367 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2368 pcbStructInfo);
2372 __EXCEPT_PAGE_FAULT
2374 SetLastError(STATUS_ACCESS_VIOLATION);
2376 __ENDTRY
2377 return ret;
2380 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2381 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2382 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2384 BOOL ret;
2385 struct AsnDecodeSequenceItem items[] = {
2386 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version), CRYPT_AsnDecodeInt,
2387 sizeof(DWORD), FALSE, FALSE, 0, 0 },
2388 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2389 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2390 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2391 0 },
2392 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2393 CRYPT_AsnDecodePKCSContentInfoInternal,
2394 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2395 ContentInfo.pszObjId), 0 },
2396 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2397 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2398 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2401 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
2402 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2403 pDecodePara, digestedData, pcbDigestedData, NULL);
2404 return ret;
2407 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2408 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2409 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2411 BOOL ret = TRUE;
2413 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2414 pDecodePara, pvStructInfo, *pcbStructInfo);
2416 __TRY
2418 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2419 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2420 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2422 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2423 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2425 __EXCEPT_PAGE_FAULT
2427 SetLastError(STATUS_ACCESS_VIOLATION);
2428 ret = FALSE;
2430 __ENDTRY
2431 return ret;
2434 struct PATH_LEN_CONSTRAINT
2436 BOOL fPathLenConstraint;
2437 DWORD dwPathLenConstraint;
2440 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2441 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2442 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2444 BOOL ret = TRUE;
2446 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2447 pvStructInfo, *pcbStructInfo);
2449 if (cbEncoded)
2451 if (pbEncoded[0] == ASN_INTEGER)
2453 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2455 if (!pvStructInfo)
2456 *pcbStructInfo = bytesNeeded;
2457 else if (*pcbStructInfo < bytesNeeded)
2459 SetLastError(ERROR_MORE_DATA);
2460 *pcbStructInfo = bytesNeeded;
2461 ret = FALSE;
2463 else
2465 struct PATH_LEN_CONSTRAINT *constraint =
2466 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2467 DWORD size = sizeof(constraint->dwPathLenConstraint);
2469 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2470 pbEncoded, cbEncoded, 0, NULL,
2471 &constraint->dwPathLenConstraint, &size);
2472 if (ret)
2473 constraint->fPathLenConstraint = TRUE;
2474 TRACE("got an int, dwPathLenConstraint is %d\n",
2475 constraint->dwPathLenConstraint);
2478 else
2480 SetLastError(CRYPT_E_ASN1_CORRUPT);
2481 ret = FALSE;
2484 TRACE("returning %d (%08x)\n", ret, GetLastError());
2485 return ret;
2488 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2489 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2490 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2492 BOOL ret;
2493 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2494 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2495 offsetof(CERT_NAME_BLOB, pbData) };
2496 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2498 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2499 pDecodePara, pvStructInfo, *pcbStructInfo);
2501 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2502 pDecodePara, pvStructInfo, pcbStructInfo,
2503 entries ? entries->rgItems : NULL);
2504 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2505 return ret;
2508 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2509 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2510 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2512 BOOL ret;
2514 __TRY
2516 struct AsnDecodeSequenceItem items[] = {
2517 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2518 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2519 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2520 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2521 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2522 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2523 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2524 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2525 sizeof(struct GenericArray), TRUE, TRUE,
2526 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2529 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2530 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2531 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2533 __EXCEPT_PAGE_FAULT
2535 SetLastError(STATUS_ACCESS_VIOLATION);
2536 ret = FALSE;
2538 __ENDTRY
2539 return ret;
2542 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2543 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2544 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2546 BOOL ret;
2548 __TRY
2550 struct AsnDecodeSequenceItem items[] = {
2551 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2552 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2553 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2554 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2555 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2558 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2559 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2560 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2562 __EXCEPT_PAGE_FAULT
2564 SetLastError(STATUS_ACCESS_VIOLATION);
2565 ret = FALSE;
2567 __ENDTRY
2568 return ret;
2571 #define RSA1_MAGIC 0x31415352
2573 struct DECODED_RSA_PUB_KEY
2575 DWORD pubexp;
2576 CRYPT_INTEGER_BLOB modulus;
2579 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2580 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2581 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2583 BOOL ret;
2585 __TRY
2587 struct AsnDecodeSequenceItem items[] = {
2588 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2589 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2590 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2591 0 },
2592 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2593 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2595 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2596 DWORD size = 0;
2598 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2599 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2600 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2601 if (ret)
2603 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2604 decodedKey->modulus.cbData;
2606 if (!pvStructInfo)
2608 *pcbStructInfo = bytesNeeded;
2609 ret = TRUE;
2611 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2612 pvStructInfo, pcbStructInfo, bytesNeeded)))
2614 BLOBHEADER *hdr;
2615 RSAPUBKEY *rsaPubKey;
2617 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2618 pvStructInfo = *(BYTE **)pvStructInfo;
2619 hdr = (BLOBHEADER *)pvStructInfo;
2620 hdr->bType = PUBLICKEYBLOB;
2621 hdr->bVersion = CUR_BLOB_VERSION;
2622 hdr->reserved = 0;
2623 hdr->aiKeyAlg = CALG_RSA_KEYX;
2624 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2625 sizeof(BLOBHEADER));
2626 rsaPubKey->magic = RSA1_MAGIC;
2627 rsaPubKey->pubexp = decodedKey->pubexp;
2628 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2629 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2630 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2631 decodedKey->modulus.cbData);
2633 LocalFree(decodedKey);
2636 __EXCEPT_PAGE_FAULT
2638 SetLastError(STATUS_ACCESS_VIOLATION);
2639 ret = FALSE;
2641 __ENDTRY
2642 return ret;
2645 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2646 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2647 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2649 BOOL ret;
2650 DWORD bytesNeeded, dataLen;
2652 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2653 pDecodePara, pvStructInfo, *pcbStructInfo);
2655 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2657 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2658 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2659 else
2660 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2661 if (!pvStructInfo)
2662 *pcbStructInfo = bytesNeeded;
2663 else if (*pcbStructInfo < bytesNeeded)
2665 SetLastError(ERROR_MORE_DATA);
2666 *pcbStructInfo = bytesNeeded;
2667 ret = FALSE;
2669 else
2671 CRYPT_DATA_BLOB *blob;
2672 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2674 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2675 blob->cbData = dataLen;
2676 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2677 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2678 else
2680 assert(blob->pbData);
2681 if (blob->cbData)
2682 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2683 blob->cbData);
2687 return ret;
2690 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2691 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2692 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2694 BOOL ret;
2696 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2697 pDecodePara, pvStructInfo, *pcbStructInfo);
2699 __TRY
2701 DWORD bytesNeeded;
2703 if (!cbEncoded)
2705 SetLastError(CRYPT_E_ASN1_CORRUPT);
2706 ret = FALSE;
2708 else if (pbEncoded[0] != ASN_OCTETSTRING)
2710 SetLastError(CRYPT_E_ASN1_BADTAG);
2711 ret = FALSE;
2713 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2714 lpszStructType, pbEncoded, cbEncoded,
2715 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2717 if (!pvStructInfo)
2718 *pcbStructInfo = bytesNeeded;
2719 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2720 pvStructInfo, pcbStructInfo, bytesNeeded)))
2722 CRYPT_DATA_BLOB *blob;
2724 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2725 pvStructInfo = *(BYTE **)pvStructInfo;
2726 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2727 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2728 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2729 lpszStructType, pbEncoded, cbEncoded,
2730 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2731 &bytesNeeded);
2735 __EXCEPT_PAGE_FAULT
2737 SetLastError(STATUS_ACCESS_VIOLATION);
2738 ret = FALSE;
2740 __ENDTRY
2741 return ret;
2744 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2745 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2746 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2748 BOOL ret;
2750 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2751 pDecodePara, pvStructInfo, *pcbStructInfo);
2753 if (pbEncoded[0] == ASN_BITSTRING)
2755 DWORD bytesNeeded, dataLen;
2757 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2759 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2760 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2761 else
2762 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2763 if (!pvStructInfo)
2764 *pcbStructInfo = bytesNeeded;
2765 else if (*pcbStructInfo < bytesNeeded)
2767 *pcbStructInfo = bytesNeeded;
2768 SetLastError(ERROR_MORE_DATA);
2769 ret = FALSE;
2771 else
2773 CRYPT_BIT_BLOB *blob;
2775 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2776 blob->cbData = dataLen - 1;
2777 blob->cUnusedBits = *(pbEncoded + 1 +
2778 GET_LEN_BYTES(pbEncoded[1]));
2779 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2781 blob->pbData = (BYTE *)pbEncoded + 2 +
2782 GET_LEN_BYTES(pbEncoded[1]);
2784 else
2786 assert(blob->pbData);
2787 if (blob->cbData)
2789 BYTE mask = 0xff << blob->cUnusedBits;
2791 memcpy(blob->pbData, pbEncoded + 2 +
2792 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2793 blob->pbData[blob->cbData - 1] &= mask;
2799 else
2801 SetLastError(CRYPT_E_ASN1_BADTAG);
2802 ret = FALSE;
2804 TRACE("returning %d (%08x)\n", ret, GetLastError());
2805 return ret;
2808 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2809 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2810 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2812 BOOL ret;
2814 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2815 pDecodePara, pvStructInfo, pcbStructInfo);
2817 __TRY
2819 DWORD bytesNeeded;
2821 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2822 lpszStructType, pbEncoded, cbEncoded,
2823 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2825 if (!pvStructInfo)
2826 *pcbStructInfo = bytesNeeded;
2827 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2828 pvStructInfo, pcbStructInfo, bytesNeeded)))
2830 CRYPT_BIT_BLOB *blob;
2832 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2833 pvStructInfo = *(BYTE **)pvStructInfo;
2834 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2835 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2836 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2837 lpszStructType, pbEncoded, cbEncoded,
2838 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2839 &bytesNeeded);
2843 __EXCEPT_PAGE_FAULT
2845 SetLastError(STATUS_ACCESS_VIOLATION);
2846 ret = FALSE;
2848 __ENDTRY
2849 TRACE("returning %d (%08x)\n", ret, GetLastError());
2850 return ret;
2853 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2854 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2855 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2857 BOOL ret;
2859 if (!pvStructInfo)
2861 *pcbStructInfo = sizeof(int);
2862 return TRUE;
2864 __TRY
2866 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2867 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2868 DWORD size = sizeof(buf);
2870 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2871 if (pbEncoded[0] != ASN_INTEGER)
2873 SetLastError(CRYPT_E_ASN1_BADTAG);
2874 ret = FALSE;
2876 else
2877 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2878 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
2879 &size);
2880 if (ret)
2882 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2883 pvStructInfo, pcbStructInfo, sizeof(int))))
2885 int val, i;
2887 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2888 pvStructInfo = *(BYTE **)pvStructInfo;
2889 if (blob->pbData[blob->cbData - 1] & 0x80)
2891 /* initialize to a negative value to sign-extend */
2892 val = -1;
2894 else
2895 val = 0;
2896 for (i = 0; i < blob->cbData; i++)
2898 val <<= 8;
2899 val |= blob->pbData[blob->cbData - i - 1];
2901 memcpy(pvStructInfo, &val, sizeof(int));
2904 else if (GetLastError() == ERROR_MORE_DATA)
2905 SetLastError(CRYPT_E_ASN1_LARGE);
2907 __EXCEPT_PAGE_FAULT
2909 SetLastError(STATUS_ACCESS_VIOLATION);
2910 ret = FALSE;
2912 __ENDTRY
2913 return ret;
2916 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2917 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2918 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2920 BOOL ret;
2921 DWORD bytesNeeded, dataLen;
2923 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2925 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2927 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2928 if (!pvStructInfo)
2929 *pcbStructInfo = bytesNeeded;
2930 else if (*pcbStructInfo < bytesNeeded)
2932 *pcbStructInfo = bytesNeeded;
2933 SetLastError(ERROR_MORE_DATA);
2934 ret = FALSE;
2936 else
2938 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2940 blob->cbData = dataLen;
2941 assert(blob->pbData);
2942 if (blob->cbData)
2944 DWORD i;
2946 for (i = 0; i < blob->cbData; i++)
2948 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2949 dataLen - i - 1);
2954 return ret;
2957 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2958 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2959 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2961 BOOL ret;
2963 __TRY
2965 DWORD bytesNeeded;
2967 if (pbEncoded[0] != ASN_INTEGER)
2969 SetLastError(CRYPT_E_ASN1_BADTAG);
2970 ret = FALSE;
2972 else
2973 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2974 lpszStructType, pbEncoded, cbEncoded,
2975 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
2976 if (ret)
2978 if (!pvStructInfo)
2979 *pcbStructInfo = bytesNeeded;
2980 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2981 pvStructInfo, pcbStructInfo, bytesNeeded)))
2983 CRYPT_INTEGER_BLOB *blob;
2985 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2986 pvStructInfo = *(BYTE **)pvStructInfo;
2987 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2988 blob->pbData = (BYTE *)pvStructInfo +
2989 sizeof(CRYPT_INTEGER_BLOB);
2990 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2991 lpszStructType, pbEncoded, cbEncoded,
2992 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2993 &bytesNeeded);
2997 __EXCEPT_PAGE_FAULT
2999 SetLastError(STATUS_ACCESS_VIOLATION);
3000 ret = FALSE;
3002 __ENDTRY
3003 return ret;
3006 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
3007 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3008 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3009 void *pvStructInfo, DWORD *pcbStructInfo)
3011 BOOL ret;
3013 if (pbEncoded[0] == ASN_INTEGER)
3015 DWORD bytesNeeded, dataLen;
3017 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3019 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3021 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3022 if (!pvStructInfo)
3023 *pcbStructInfo = bytesNeeded;
3024 else if (*pcbStructInfo < bytesNeeded)
3026 *pcbStructInfo = bytesNeeded;
3027 SetLastError(ERROR_MORE_DATA);
3028 ret = FALSE;
3030 else
3032 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3034 blob->cbData = dataLen;
3035 assert(blob->pbData);
3036 /* remove leading zero byte if it exists */
3037 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3039 blob->cbData--;
3040 blob->pbData++;
3042 if (blob->cbData)
3044 DWORD i;
3046 for (i = 0; i < blob->cbData; i++)
3048 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3049 dataLen - i - 1);
3055 else
3057 SetLastError(CRYPT_E_ASN1_BADTAG);
3058 ret = FALSE;
3060 return ret;
3063 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3064 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3065 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3067 BOOL ret;
3069 __TRY
3071 DWORD bytesNeeded;
3073 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3074 lpszStructType, pbEncoded, cbEncoded,
3075 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
3077 if (!pvStructInfo)
3078 *pcbStructInfo = bytesNeeded;
3079 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3080 pvStructInfo, pcbStructInfo, bytesNeeded)))
3082 CRYPT_INTEGER_BLOB *blob;
3084 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3085 pvStructInfo = *(BYTE **)pvStructInfo;
3086 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3087 blob->pbData = (BYTE *)pvStructInfo +
3088 sizeof(CRYPT_INTEGER_BLOB);
3089 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3090 lpszStructType, pbEncoded, cbEncoded,
3091 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3092 &bytesNeeded);
3096 __EXCEPT_PAGE_FAULT
3098 SetLastError(STATUS_ACCESS_VIOLATION);
3099 ret = FALSE;
3101 __ENDTRY
3102 return ret;
3105 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3106 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3107 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3109 BOOL ret;
3111 if (!pvStructInfo)
3113 *pcbStructInfo = sizeof(int);
3114 return TRUE;
3116 __TRY
3118 if (pbEncoded[0] == ASN_ENUMERATED)
3120 unsigned int val = 0, i;
3122 if (cbEncoded <= 1)
3124 SetLastError(CRYPT_E_ASN1_EOD);
3125 ret = FALSE;
3127 else if (pbEncoded[1] == 0)
3129 SetLastError(CRYPT_E_ASN1_CORRUPT);
3130 ret = FALSE;
3132 else
3134 /* A little strange looking, but we have to accept a sign byte:
3135 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3136 * assuming a small length is okay here, it has to be in short
3137 * form.
3139 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3141 SetLastError(CRYPT_E_ASN1_LARGE);
3142 return FALSE;
3144 for (i = 0; i < pbEncoded[1]; i++)
3146 val <<= 8;
3147 val |= pbEncoded[2 + i];
3149 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3150 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3152 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3153 pvStructInfo = *(BYTE **)pvStructInfo;
3154 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3158 else
3160 SetLastError(CRYPT_E_ASN1_BADTAG);
3161 ret = FALSE;
3164 __EXCEPT_PAGE_FAULT
3166 SetLastError(STATUS_ACCESS_VIOLATION);
3167 ret = FALSE;
3169 __ENDTRY
3170 return ret;
3173 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3174 * if it fails.
3176 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3177 do { \
3178 BYTE i; \
3180 (word) = 0; \
3181 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3183 if (!isdigit(*(pbEncoded))) \
3185 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3186 ret = FALSE; \
3188 else \
3190 (word) *= 10; \
3191 (word) += *(pbEncoded)++ - '0'; \
3194 } while (0)
3196 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3197 SYSTEMTIME *sysTime)
3199 BOOL ret;
3201 __TRY
3203 ret = TRUE;
3204 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3206 WORD hours, minutes = 0;
3207 BYTE sign = *pbEncoded++;
3209 len--;
3210 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3211 if (ret && hours >= 24)
3213 SetLastError(CRYPT_E_ASN1_CORRUPT);
3214 ret = FALSE;
3216 else if (len >= 2)
3218 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3219 if (ret && minutes >= 60)
3221 SetLastError(CRYPT_E_ASN1_CORRUPT);
3222 ret = FALSE;
3225 if (ret)
3227 if (sign == '+')
3229 sysTime->wHour += hours;
3230 sysTime->wMinute += minutes;
3232 else
3234 if (hours > sysTime->wHour)
3236 sysTime->wDay--;
3237 sysTime->wHour = 24 - (hours - sysTime->wHour);
3239 else
3240 sysTime->wHour -= hours;
3241 if (minutes > sysTime->wMinute)
3243 sysTime->wHour--;
3244 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3246 else
3247 sysTime->wMinute -= minutes;
3252 __EXCEPT_PAGE_FAULT
3254 SetLastError(STATUS_ACCESS_VIOLATION);
3255 ret = FALSE;
3257 __ENDTRY
3258 return ret;
3261 #define MIN_ENCODED_TIME_LENGTH 10
3263 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3264 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3265 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3267 BOOL ret;
3269 if (!pvStructInfo)
3271 *pcbStructInfo = sizeof(FILETIME);
3272 return TRUE;
3274 __TRY
3276 ret = TRUE;
3277 if (pbEncoded[0] == ASN_UTCTIME)
3279 if (cbEncoded <= 1)
3281 SetLastError(CRYPT_E_ASN1_EOD);
3282 ret = FALSE;
3284 else if (pbEncoded[1] > 0x7f)
3286 /* long-form date strings really can't be valid */
3287 SetLastError(CRYPT_E_ASN1_CORRUPT);
3288 ret = FALSE;
3290 else
3292 SYSTEMTIME sysTime = { 0 };
3293 BYTE len = pbEncoded[1];
3295 if (len < MIN_ENCODED_TIME_LENGTH)
3297 SetLastError(CRYPT_E_ASN1_CORRUPT);
3298 ret = FALSE;
3300 else
3302 pbEncoded += 2;
3303 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3304 if (sysTime.wYear >= 50)
3305 sysTime.wYear += 1900;
3306 else
3307 sysTime.wYear += 2000;
3308 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3309 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3310 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3311 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3312 if (ret && len > 0)
3314 if (len >= 2 && isdigit(*pbEncoded) &&
3315 isdigit(*(pbEncoded + 1)))
3316 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3317 sysTime.wSecond);
3318 else if (isdigit(*pbEncoded))
3319 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3320 sysTime.wSecond);
3321 if (ret)
3322 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3323 &sysTime);
3325 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3326 pDecodePara, pvStructInfo, pcbStructInfo,
3327 sizeof(FILETIME))))
3329 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3330 pvStructInfo = *(BYTE **)pvStructInfo;
3331 ret = SystemTimeToFileTime(&sysTime,
3332 (FILETIME *)pvStructInfo);
3337 else
3339 SetLastError(CRYPT_E_ASN1_BADTAG);
3340 ret = FALSE;
3343 __EXCEPT_PAGE_FAULT
3345 SetLastError(STATUS_ACCESS_VIOLATION);
3346 ret = FALSE;
3348 __ENDTRY
3349 return ret;
3352 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3353 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3354 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3356 BOOL ret;
3358 if (!pvStructInfo)
3360 *pcbStructInfo = sizeof(FILETIME);
3361 return TRUE;
3363 __TRY
3365 ret = TRUE;
3366 if (pbEncoded[0] == ASN_GENERALTIME)
3368 if (cbEncoded <= 1)
3370 SetLastError(CRYPT_E_ASN1_EOD);
3371 ret = FALSE;
3373 else if (pbEncoded[1] > 0x7f)
3375 /* long-form date strings really can't be valid */
3376 SetLastError(CRYPT_E_ASN1_CORRUPT);
3377 ret = FALSE;
3379 else
3381 BYTE len = pbEncoded[1];
3383 if (len < MIN_ENCODED_TIME_LENGTH)
3385 SetLastError(CRYPT_E_ASN1_CORRUPT);
3386 ret = FALSE;
3388 else
3390 SYSTEMTIME sysTime = { 0 };
3392 pbEncoded += 2;
3393 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3394 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3395 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3396 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3397 if (ret && len > 0)
3399 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3400 sysTime.wMinute);
3401 if (ret && len > 0)
3402 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3403 sysTime.wSecond);
3404 if (ret && len > 0 && (*pbEncoded == '.' ||
3405 *pbEncoded == ','))
3407 BYTE digits;
3409 pbEncoded++;
3410 len--;
3411 /* workaround macro weirdness */
3412 digits = min(len, 3);
3413 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3414 sysTime.wMilliseconds);
3416 if (ret)
3417 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3418 &sysTime);
3420 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3421 pDecodePara, pvStructInfo, pcbStructInfo,
3422 sizeof(FILETIME))))
3424 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3425 pvStructInfo = *(BYTE **)pvStructInfo;
3426 ret = SystemTimeToFileTime(&sysTime,
3427 (FILETIME *)pvStructInfo);
3432 else
3434 SetLastError(CRYPT_E_ASN1_BADTAG);
3435 ret = FALSE;
3438 __EXCEPT_PAGE_FAULT
3440 SetLastError(STATUS_ACCESS_VIOLATION);
3441 ret = FALSE;
3443 __ENDTRY
3444 return ret;
3447 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3448 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3449 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3451 BOOL ret;
3453 __TRY
3455 if (pbEncoded[0] == ASN_UTCTIME)
3456 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3457 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3458 pcbStructInfo);
3459 else if (pbEncoded[0] == ASN_GENERALTIME)
3460 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3461 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3462 pvStructInfo, pcbStructInfo);
3463 else
3465 SetLastError(CRYPT_E_ASN1_BADTAG);
3466 ret = FALSE;
3469 __EXCEPT_PAGE_FAULT
3471 SetLastError(STATUS_ACCESS_VIOLATION);
3472 ret = FALSE;
3474 __ENDTRY
3475 return ret;
3478 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3479 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3480 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3482 BOOL ret = TRUE;
3484 __TRY
3486 if (pbEncoded[0] == ASN_SEQUENCEOF)
3488 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3490 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3492 BYTE lenBytes;
3493 const BYTE *ptr;
3495 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3496 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3497 cValue = 0;
3498 ptr = pbEncoded + 1 + lenBytes;
3499 remainingLen = dataLen;
3500 while (ret && remainingLen)
3502 DWORD nextLen;
3504 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3505 if (ret)
3507 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3509 remainingLen -= 1 + nextLenBytes + nextLen;
3510 ptr += 1 + nextLenBytes + nextLen;
3511 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3512 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3513 bytesNeeded += 1 + nextLenBytes + nextLen;
3514 cValue++;
3517 if (ret)
3519 CRYPT_SEQUENCE_OF_ANY *seq;
3520 BYTE *nextPtr;
3521 DWORD i;
3523 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3524 pvStructInfo, pcbStructInfo, bytesNeeded)))
3526 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3527 pvStructInfo = *(BYTE **)pvStructInfo;
3528 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3529 seq->cValue = cValue;
3530 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3531 sizeof(*seq));
3532 nextPtr = (BYTE *)seq->rgValue +
3533 cValue * sizeof(CRYPT_DER_BLOB);
3534 ptr = pbEncoded + 1 + lenBytes;
3535 remainingLen = dataLen;
3536 i = 0;
3537 while (ret && remainingLen)
3539 DWORD nextLen;
3541 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3542 if (ret)
3544 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3546 seq->rgValue[i].cbData = 1 + nextLenBytes +
3547 nextLen;
3548 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3549 seq->rgValue[i].pbData = (BYTE *)ptr;
3550 else
3552 seq->rgValue[i].pbData = nextPtr;
3553 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3554 nextLen);
3555 nextPtr += 1 + nextLenBytes + nextLen;
3557 remainingLen -= 1 + nextLenBytes + nextLen;
3558 ptr += 1 + nextLenBytes + nextLen;
3559 i++;
3566 else
3568 SetLastError(CRYPT_E_ASN1_BADTAG);
3569 ret = FALSE;
3572 __EXCEPT_PAGE_FAULT
3574 SetLastError(STATUS_ACCESS_VIOLATION);
3575 ret = FALSE;
3577 __ENDTRY
3578 return ret;
3581 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3582 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3583 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3585 BOOL ret;
3587 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3589 DWORD bytesNeeded, dataLen;
3591 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3593 struct AsnArrayDescriptor arrayDesc = {
3594 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3595 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3596 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3597 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3599 if (dataLen)
3601 DWORD nameLen;
3603 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3604 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3605 0, NULL, NULL, &nameLen, NULL);
3606 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3608 else
3609 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3610 if (!pvStructInfo)
3611 *pcbStructInfo = bytesNeeded;
3612 else if (*pcbStructInfo < bytesNeeded)
3614 *pcbStructInfo = bytesNeeded;
3615 SetLastError(ERROR_MORE_DATA);
3616 ret = FALSE;
3618 else
3620 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3622 if (dataLen)
3624 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3625 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3626 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3627 0, NULL, &name->u.FullName, pcbStructInfo,
3628 name->u.FullName.rgAltEntry);
3630 else
3631 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3635 else
3637 SetLastError(CRYPT_E_ASN1_BADTAG);
3638 ret = FALSE;
3640 return ret;
3643 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3644 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3645 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3647 struct AsnDecodeSequenceItem items[] = {
3648 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3649 DistPointName), CRYPT_AsnDecodeDistPointName,
3650 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3651 DistPointName.u.FullName.rgAltEntry), 0 },
3652 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3653 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3654 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3655 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3656 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3657 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3659 BOOL ret;
3661 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3662 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3663 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3664 return ret;
3667 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3668 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3669 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3671 BOOL ret;
3673 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3674 pDecodePara, pvStructInfo, *pcbStructInfo);
3676 __TRY
3678 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3679 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3680 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3682 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3683 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3685 __EXCEPT_PAGE_FAULT
3687 SetLastError(STATUS_ACCESS_VIOLATION);
3688 ret = FALSE;
3690 __ENDTRY
3691 return ret;
3694 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3695 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3696 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3698 BOOL ret;
3700 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3701 pDecodePara, pvStructInfo, *pcbStructInfo);
3703 __TRY
3705 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3706 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3708 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3709 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3711 __EXCEPT_PAGE_FAULT
3713 SetLastError(STATUS_ACCESS_VIOLATION);
3714 ret = FALSE;
3716 __ENDTRY
3717 return ret;
3720 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3721 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3722 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3724 BOOL ret;
3726 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3727 pDecodePara, pvStructInfo, *pcbStructInfo);
3729 __TRY
3731 struct AsnDecodeSequenceItem items[] = {
3732 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3733 DistPointName), CRYPT_AsnDecodeDistPointName,
3734 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3735 offsetof(CRL_ISSUING_DIST_POINT,
3736 DistPointName.u.FullName.rgAltEntry), 0 },
3737 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3738 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3739 FALSE, 0 },
3740 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3741 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3742 FALSE, 0 },
3743 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3744 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3745 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3746 OnlySomeReasonFlags.pbData), 0 },
3747 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3748 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3751 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3752 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3753 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3755 __EXCEPT_PAGE_FAULT
3757 SetLastError(STATUS_ACCESS_VIOLATION);
3758 ret = FALSE;
3760 __ENDTRY
3761 return ret;
3764 static BOOL WINAPI CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType,
3765 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3766 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3768 BOOL ret;
3769 struct AsnDecodeSequenceItem items[] = {
3770 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
3771 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
3772 Issuer.pbData) },
3773 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
3774 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
3775 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
3777 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3778 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3780 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3781 pDecodePara, pvStructInfo, *pcbStructInfo);
3783 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3784 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3785 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
3786 issuerSerial ? issuerSerial->Issuer.pbData : NULL);
3787 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
3789 SetLastError(CRYPT_E_ASN1_CORRUPT);
3790 ret = FALSE;
3792 TRACE("returning %d\n", ret);
3793 return ret;
3796 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
3797 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3798 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3800 BOOL ret = FALSE;
3802 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3803 pDecodePara, pvStructInfo, *pcbStructInfo);
3805 __TRY
3807 struct AsnDecodeSequenceItem items[] = {
3808 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
3809 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3810 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
3811 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
3812 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
3813 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
3814 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3815 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
3816 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
3817 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3818 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
3819 HashEncryptionAlgorithm.pszObjId), 0 },
3820 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CMSG_SIGNER_INFO, AuthAttrs),
3821 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3822 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
3823 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
3824 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3825 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
3826 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
3827 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
3828 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
3831 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3832 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3833 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3835 __EXCEPT_PAGE_FAULT
3837 SetLastError(STATUS_ACCESS_VIOLATION);
3839 __ENDTRY
3840 TRACE("returning %d\n", ret);
3841 return ret;
3844 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3845 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3846 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3848 static HCRYPTOIDFUNCSET set = NULL;
3849 BOOL ret = FALSE;
3850 CryptDecodeObjectExFunc decodeFunc = NULL;
3851 HCRYPTOIDFUNCADDR hFunc = NULL;
3853 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
3854 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
3855 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3857 if (!pvStructInfo && !pcbStructInfo)
3859 SetLastError(ERROR_INVALID_PARAMETER);
3860 return FALSE;
3862 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3863 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3865 SetLastError(ERROR_FILE_NOT_FOUND);
3866 return FALSE;
3868 if (!cbEncoded)
3870 SetLastError(CRYPT_E_ASN1_EOD);
3871 return FALSE;
3873 if (cbEncoded > MAX_ENCODED_LEN)
3875 SetLastError(CRYPT_E_ASN1_LARGE);
3876 return FALSE;
3879 SetLastError(NOERROR);
3880 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3881 *(BYTE **)pvStructInfo = NULL;
3882 if (!HIWORD(lpszStructType))
3884 switch (LOWORD(lpszStructType))
3886 case (WORD)X509_CERT:
3887 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3888 break;
3889 case (WORD)X509_CERT_TO_BE_SIGNED:
3890 decodeFunc = CRYPT_AsnDecodeCert;
3891 break;
3892 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3893 decodeFunc = CRYPT_AsnDecodeCRL;
3894 break;
3895 case (WORD)X509_EXTENSIONS:
3896 decodeFunc = CRYPT_AsnDecodeExtensions;
3897 break;
3898 case (WORD)X509_NAME_VALUE:
3899 decodeFunc = CRYPT_AsnDecodeNameValue;
3900 break;
3901 case (WORD)X509_NAME:
3902 decodeFunc = CRYPT_AsnDecodeName;
3903 break;
3904 case (WORD)X509_PUBLIC_KEY_INFO:
3905 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
3906 break;
3907 case (WORD)X509_AUTHORITY_KEY_ID:
3908 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3909 break;
3910 case (WORD)X509_ALTERNATE_NAME:
3911 decodeFunc = CRYPT_AsnDecodeAltName;
3912 break;
3913 case (WORD)X509_BASIC_CONSTRAINTS:
3914 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3915 break;
3916 case (WORD)X509_BASIC_CONSTRAINTS2:
3917 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3918 break;
3919 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3920 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3921 break;
3922 case (WORD)X509_UNICODE_NAME:
3923 decodeFunc = CRYPT_AsnDecodeUnicodeName;
3924 break;
3925 case (WORD)PKCS_ATTRIBUTE:
3926 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
3927 break;
3928 case (WORD)X509_UNICODE_NAME_VALUE:
3929 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
3930 break;
3931 case (WORD)X509_OCTET_STRING:
3932 decodeFunc = CRYPT_AsnDecodeOctets;
3933 break;
3934 case (WORD)X509_BITS:
3935 case (WORD)X509_KEY_USAGE:
3936 decodeFunc = CRYPT_AsnDecodeBits;
3937 break;
3938 case (WORD)X509_INTEGER:
3939 decodeFunc = CRYPT_AsnDecodeInt;
3940 break;
3941 case (WORD)X509_MULTI_BYTE_INTEGER:
3942 decodeFunc = CRYPT_AsnDecodeInteger;
3943 break;
3944 case (WORD)X509_MULTI_BYTE_UINT:
3945 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3946 break;
3947 case (WORD)X509_ENUMERATED:
3948 decodeFunc = CRYPT_AsnDecodeEnumerated;
3949 break;
3950 case (WORD)X509_CHOICE_OF_TIME:
3951 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3952 break;
3953 case (WORD)X509_AUTHORITY_KEY_ID2:
3954 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
3955 break;
3956 case (WORD)PKCS_CONTENT_INFO:
3957 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
3958 break;
3959 case (WORD)X509_SEQUENCE_OF_ANY:
3960 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3961 break;
3962 case (WORD)PKCS_UTC_TIME:
3963 decodeFunc = CRYPT_AsnDecodeUtcTime;
3964 break;
3965 case (WORD)X509_CRL_DIST_POINTS:
3966 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3967 break;
3968 case (WORD)X509_ENHANCED_KEY_USAGE:
3969 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3970 break;
3971 case (WORD)PKCS_ATTRIBUTES:
3972 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
3973 break;
3974 case (WORD)X509_ISSUING_DIST_POINT:
3975 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3976 break;
3977 case (WORD)PKCS7_SIGNER_INFO:
3978 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
3979 break;
3980 default:
3981 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3984 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3985 decodeFunc = CRYPT_AsnDecodeExtensions;
3986 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3987 decodeFunc = CRYPT_AsnDecodeUtcTime;
3988 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3989 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3990 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3991 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
3992 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3993 decodeFunc = CRYPT_AsnDecodeEnumerated;
3994 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3995 decodeFunc = CRYPT_AsnDecodeBits;
3996 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3997 decodeFunc = CRYPT_AsnDecodeOctets;
3998 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3999 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4000 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4001 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4002 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4003 decodeFunc = CRYPT_AsnDecodeAltName;
4004 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4005 decodeFunc = CRYPT_AsnDecodeAltName;
4006 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4007 decodeFunc = CRYPT_AsnDecodeAltName;
4008 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4009 decodeFunc = CRYPT_AsnDecodeAltName;
4010 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4011 decodeFunc = CRYPT_AsnDecodeAltName;
4012 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4013 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4014 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4015 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4016 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4017 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4018 else
4019 TRACE("OID %s not found or unimplemented, looking for DLL\n",
4020 debugstr_a(lpszStructType));
4021 if (!decodeFunc)
4023 if (!set)
4024 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4025 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4026 (void **)&decodeFunc, &hFunc);
4028 if (decodeFunc)
4029 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4030 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4031 else
4032 SetLastError(ERROR_FILE_NOT_FOUND);
4033 if (hFunc)
4034 CryptFreeOIDFunctionAddress(hFunc, 0);
4035 return ret;