crypt32: Implement DecodeAltName with DecodeAltNameInternal.
[wine.git] / dlls / crypt32 / decode.c
blobe96757f696bff410fa0087b0126693e71416d874
1 /*
2 * Copyright 2005-2007 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 isn't
21 * implemented, 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 "Constants for CryptEncodeObject and CryptDecodeObject"
33 #include <assert.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
38 #define NONAMELESSUNION
40 #include "windef.h"
41 #include "winbase.h"
42 #include "wincrypt.h"
43 #include "winnls.h"
44 #include "snmp.h"
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "crypt32_private.h"
49 /* This is a bit arbitrary, but to set some limit: */
50 #define MAX_ENCODED_LEN 0x02000000
52 #define ASN_FLAGS_MASK 0xe0
53 #define ASN_TYPE_MASK 0x1f
55 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
56 WINE_DECLARE_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 /* Internal decoders don't do memory allocation or exception handling, and
70 * they report how many bytes they decoded.
72 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
73 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
75 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
76 * The dwCertEncodingType and lpszStructType are ignored by the built-in
77 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
78 * since it must call functions in external DLLs that follow these signatures.
80 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
81 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
82 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
83 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
84 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
85 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
86 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
87 * time, doesn't do memory allocation, and doesn't do exception handling.
88 * (This isn't intended to be the externally-called one.)
90 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
92 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
93 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
94 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
95 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
96 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
97 /* Internal function */
98 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
99 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
100 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
101 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
102 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
103 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
104 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
105 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
106 * member has been initialized, doesn't do exception handling, and doesn't do
107 * memory allocation.
109 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
110 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
111 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
112 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
113 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
114 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
115 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
116 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
117 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
118 static BOOL WINAPI CRYPT_AsnDecodeIntInternal(DWORD dwCertEncodingType,
119 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
120 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
121 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
122 * member has been initialized, doesn't do exception handling, and doesn't do
123 * memory allocation. Also doesn't check tag, assumes the caller has checked
124 * it.
126 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
127 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
128 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
129 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
130 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
131 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
132 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
133 void *pvStructInfo, DWORD *pcbStructInfo);
135 /* Gets the number of length bytes from the given (leading) length byte */
136 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
138 /* Helper function to get the encoded length of the data starting at pbEncoded,
139 * where pbEncoded[0] is the tag. If the data are too short to contain a
140 * length or if the length is too large for cbEncoded, sets an appropriate
141 * error code and returns FALSE. If the encoded length is unknown due to
142 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
144 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
145 DWORD *len)
147 BOOL ret;
149 if (cbEncoded <= 1)
151 SetLastError(CRYPT_E_ASN1_CORRUPT);
152 ret = FALSE;
154 else if (pbEncoded[1] <= 0x7f)
156 if (pbEncoded[1] + 1 > cbEncoded)
158 SetLastError(CRYPT_E_ASN1_EOD);
159 ret = FALSE;
161 else
163 *len = pbEncoded[1];
164 ret = TRUE;
167 else if (pbEncoded[1] == 0x80)
169 *len = CMSG_INDEFINITE_LENGTH;
170 ret = TRUE;
172 else
174 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
176 if (lenLen > sizeof(DWORD) + 1)
178 SetLastError(CRYPT_E_ASN1_LARGE);
179 ret = FALSE;
181 else if (lenLen + 2 > cbEncoded)
183 SetLastError(CRYPT_E_ASN1_CORRUPT);
184 ret = FALSE;
186 else
188 DWORD out = 0;
190 pbEncoded += 2;
191 while (--lenLen)
193 out <<= 8;
194 out |= *pbEncoded++;
196 if (out + lenLen + 1 > cbEncoded)
198 SetLastError(CRYPT_E_ASN1_EOD);
199 ret = FALSE;
201 else
203 *len = out;
204 ret = TRUE;
208 return ret;
211 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
212 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
214 BOOL ret;
216 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
217 *len == CMSG_INDEFINITE_LENGTH)
219 SetLastError(CRYPT_E_ASN1_CORRUPT);
220 ret = FALSE;
222 return ret;
225 /* Helper function to check *pcbStructInfo, set it to the required size, and
226 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
227 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
228 * pointer to the newly allocated memory.
230 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
231 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
232 DWORD bytesNeeded)
234 BOOL ret = TRUE;
236 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
238 if (pDecodePara && pDecodePara->pfnAlloc)
239 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
240 else
241 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
242 if (!*(BYTE **)pvStructInfo)
243 ret = FALSE;
244 else
245 *pcbStructInfo = bytesNeeded;
247 else if (*pcbStructInfo < bytesNeeded)
249 *pcbStructInfo = bytesNeeded;
250 SetLastError(ERROR_MORE_DATA);
251 ret = FALSE;
253 return ret;
256 /* Helper function to check *pcbStructInfo and set it to the required size.
257 * Assumes pvStructInfo is not NULL.
259 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
261 BOOL ret;
263 if (*pcbStructInfo < bytesNeeded)
265 *pcbStructInfo = bytesNeeded;
266 SetLastError(ERROR_MORE_DATA);
267 ret = FALSE;
269 else
271 *pcbStructInfo = bytesNeeded;
272 ret = TRUE;
274 return ret;
277 /* tag:
278 * The expected tag of the item. If tag is 0, decodeFunc is called
279 * regardless of the tag value seen.
280 * offset:
281 * A sequence is decoded into a struct. The offset member is the
282 * offset of this item within that struct.
283 * decodeFunc:
284 * The decoder function to use. If this is NULL, then the member isn't
285 * decoded, but minSize space is reserved for it.
286 * minSize:
287 * The minimum amount of space occupied after decoding. You must set this.
288 * optional:
289 * If true, and the tag doesn't match the expected tag for this item,
290 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
291 * filled with 0 for this member.
292 * hasPointer, pointerOffset:
293 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
294 * the offset within the struct of the data pointer (or to the
295 * first data pointer, if more than one exist).
296 * size:
297 * Used by CRYPT_AsnDecodeSequence, not for your use.
299 struct AsnDecodeSequenceItem
301 BYTE tag;
302 DWORD offset;
303 CryptDecodeObjectExFunc decodeFunc;
304 DWORD minSize;
305 BOOL optional;
306 BOOL hasPointer;
307 DWORD pointerOffset;
308 DWORD size;
311 /* Decodes the items in a sequence, where the items are described in items,
312 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
313 * pvStructInfo. nextData is a pointer to the memory location at which the
314 * first decoded item with a dynamic pointer should point.
315 * Upon decoding, *cbDecoded is the total number of bytes decoded.
316 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
318 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
319 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
320 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
321 DWORD *cbDecoded)
323 BOOL ret;
324 DWORD i, decoded = 0;
325 const BYTE *ptr = pbEncoded;
327 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
328 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
330 for (i = 0, ret = TRUE; ret && i < cItem; i++)
332 if (cbEncoded - (ptr - pbEncoded) != 0)
334 DWORD nextItemLen;
336 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
337 &nextItemLen)))
339 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
341 if (ptr[0] == items[i].tag || !items[i].tag)
343 if (nextData && pvStructInfo && items[i].hasPointer)
345 TRACE("Setting next pointer to %p\n",
346 nextData);
347 *(BYTE **)((BYTE *)pvStructInfo +
348 items[i].pointerOffset) = nextData;
350 if (items[i].decodeFunc)
352 if (pvStructInfo)
353 TRACE("decoding item %d\n", i);
354 else
355 TRACE("sizing item %d\n", i);
356 ret = items[i].decodeFunc(dwCertEncodingType,
357 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
358 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
359 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
360 : NULL, &items[i].size);
361 if (ret)
363 /* Account for alignment padding */
364 if (items[i].size % sizeof(DWORD_PTR))
365 items[i].size += sizeof(DWORD_PTR) -
366 items[i].size % sizeof(DWORD_PTR);
367 TRACE("item %d size: %d\n", i, items[i].size);
368 if (nextData && items[i].hasPointer &&
369 items[i].size > items[i].minSize)
370 nextData += items[i].size - items[i].minSize;
371 ptr += 1 + nextItemLenBytes + nextItemLen;
372 decoded += 1 + nextItemLenBytes + nextItemLen;
373 TRACE("item %d: decoded %d bytes\n", i,
374 1 + nextItemLenBytes + nextItemLen);
376 else if (items[i].optional &&
377 GetLastError() == CRYPT_E_ASN1_BADTAG)
379 TRACE("skipping optional item %d\n", i);
380 items[i].size = items[i].minSize;
381 SetLastError(NOERROR);
382 ret = TRUE;
384 else
385 TRACE("item %d failed: %08x\n", i,
386 GetLastError());
388 else
390 TRACE("item %d: decoded %d bytes\n", i,
391 1 + nextItemLenBytes + nextItemLen);
392 ptr += 1 + nextItemLenBytes + nextItemLen;
393 decoded += 1 + nextItemLenBytes + nextItemLen;
394 items[i].size = items[i].minSize;
397 else if (items[i].optional)
399 TRACE("skipping optional item %d\n", i);
400 items[i].size = items[i].minSize;
402 else
404 TRACE("item %d: tag %02x doesn't match expected %02x\n",
405 i, ptr[0], items[i].tag);
406 SetLastError(CRYPT_E_ASN1_BADTAG);
407 ret = FALSE;
411 else if (items[i].optional)
413 TRACE("missing optional item %d, skipping\n", i);
414 items[i].size = items[i].minSize;
416 else
418 TRACE("not enough bytes for item %d, failing\n", i);
419 SetLastError(CRYPT_E_ASN1_CORRUPT);
420 ret = FALSE;
423 if (ret)
424 *cbDecoded = decoded;
425 TRACE("returning %d\n", ret);
426 return ret;
429 /* This decodes an arbitrary sequence into a contiguous block of memory
430 * (basically, a struct.) Each element being decoded is described by a struct
431 * AsnDecodeSequenceItem, see above.
432 * startingPointer is an optional pointer to the first place where dynamic
433 * data will be stored. If you know the starting offset, you may pass it
434 * here. Otherwise, pass NULL, and one will be inferred from the items.
436 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
437 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
438 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
439 void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded,
440 void *startingPointer)
442 BOOL ret;
444 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
445 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
446 startingPointer);
448 if (pbEncoded[0] == ASN_SEQUENCE)
450 DWORD dataLen;
452 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
454 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
455 const BYTE *ptr = pbEncoded + 1 + lenBytes;
457 cbEncoded -= 1 + lenBytes;
458 if (cbEncoded < dataLen)
460 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
461 cbEncoded);
462 SetLastError(CRYPT_E_ASN1_CORRUPT);
463 ret = FALSE;
465 else
466 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
467 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
468 if (ret && cbDecoded != dataLen)
470 TRACE("expected %d decoded, got %d, failing\n", dataLen,
471 cbDecoded);
472 SetLastError(CRYPT_E_ASN1_CORRUPT);
473 ret = FALSE;
475 if (ret)
477 DWORD i, bytesNeeded = 0, structSize = 0;
479 for (i = 0; i < cItem; i++)
481 bytesNeeded += items[i].size;
482 structSize += items[i].minSize;
484 if (ret && pcbDecoded)
485 *pcbDecoded = 1 + lenBytes + cbDecoded;
486 if (!pvStructInfo)
487 *pcbStructInfo = bytesNeeded;
488 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
489 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
491 BYTE *nextData;
493 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
494 pvStructInfo = *(BYTE **)pvStructInfo;
495 if (startingPointer)
496 nextData = (BYTE *)startingPointer;
497 else
498 nextData = (BYTE *)pvStructInfo + structSize;
499 memset(pvStructInfo, 0, structSize);
500 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
501 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
502 &cbDecoded);
507 else
509 SetLastError(CRYPT_E_ASN1_BADTAG);
510 ret = FALSE;
512 TRACE("returning %d (%08x)\n", ret, GetLastError());
513 return ret;
516 /* tag:
517 * The expected tag of the entire encoded array (usually a variant
518 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
519 * regardless of the tag seen.
520 * decodeFunc:
521 * used to decode each item in the array
522 * itemSize:
523 * is the minimum size of each decoded item
524 * hasPointer:
525 * indicates whether each item has a dynamic pointer
526 * pointerOffset:
527 * indicates the offset within itemSize at which the pointer exists
529 struct AsnArrayDescriptor
531 BYTE tag;
532 InternalDecodeFunc decodeFunc;
533 DWORD itemSize;
534 BOOL hasPointer;
535 DWORD pointerOffset;
538 struct AsnArrayItemSize
540 DWORD encodedLen;
541 DWORD size;
544 /* Decodes an array of like types into a struct GenericArray.
545 * The layout and decoding of the array are described by a struct
546 * AsnArrayDescriptor.
548 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
549 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
550 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
551 DWORD *pcbDecoded, void *startingPointer)
553 BOOL ret = TRUE;
555 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
556 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
557 startingPointer);
559 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
561 DWORD dataLen;
563 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
565 DWORD bytesNeeded, cItems = 0, decoded;
566 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
567 /* There can be arbitrarily many items, but there is often only one.
569 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
571 decoded = 1 + lenBytes;
572 bytesNeeded = sizeof(struct GenericArray);
573 if (dataLen)
575 const BYTE *ptr;
576 BOOL doneDecoding = FALSE;
578 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
580 DWORD itemLenBytes;
582 itemLenBytes = GET_LEN_BYTES(ptr[1]);
583 if (dataLen == CMSG_INDEFINITE_LENGTH)
585 if (ptr[0] == 0)
587 doneDecoding = TRUE;
588 if (itemLenBytes != 1 || ptr[1] != 0)
590 SetLastError(CRYPT_E_ASN1_CORRUPT);
591 ret = FALSE;
593 else
594 decoded += 2;
597 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
598 doneDecoding = TRUE;
599 if (!doneDecoding)
601 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
603 /* Each item decoded may not tolerate extraneous bytes,
604 * so get the length of the next element if known.
606 if ((ret = CRYPT_GetLengthIndefinite(ptr,
607 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
609 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
610 itemEncoded = cbEncoded - (ptr - pbEncoded);
611 else
612 itemEncoded = 1 + itemLenBytes + itemDataLen;
614 if (ret)
615 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
616 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
617 &itemDecoded);
618 if (ret)
620 cItems++;
621 if (itemSizes != &itemSize)
622 itemSizes = CryptMemRealloc(itemSizes,
623 cItems * sizeof(struct AsnArrayItemSize));
624 else if (cItems > 1)
626 itemSizes =
627 CryptMemAlloc(
628 cItems * sizeof(struct AsnArrayItemSize));
629 if (itemSizes)
630 memcpy(itemSizes, &itemSize,
631 sizeof(itemSize));
633 if (itemSizes)
635 decoded += itemDecoded;
636 itemSizes[cItems - 1].encodedLen = itemEncoded;
637 itemSizes[cItems - 1].size = size;
638 bytesNeeded += size;
639 ptr += itemEncoded;
641 else
642 ret = FALSE;
647 if (ret)
649 if (pcbDecoded)
650 *pcbDecoded = decoded;
651 if (!pvStructInfo)
652 *pcbStructInfo = bytesNeeded;
653 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
654 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
656 DWORD i;
657 BYTE *nextData;
658 const BYTE *ptr;
659 struct GenericArray *array;
661 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
662 pvStructInfo = *(BYTE **)pvStructInfo;
663 array = (struct GenericArray *)pvStructInfo;
664 array->cItems = cItems;
665 if (startingPointer)
666 array->rgItems = startingPointer;
667 else
668 array->rgItems = (BYTE *)array +
669 sizeof(struct GenericArray);
670 nextData = (BYTE *)array->rgItems +
671 array->cItems * arrayDesc->itemSize;
672 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
673 i < cItems && ptr - pbEncoded - 1 - lenBytes <
674 dataLen; i++)
676 if (arrayDesc->hasPointer)
677 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
678 + arrayDesc->pointerOffset) = nextData;
679 ret = arrayDesc->decodeFunc(ptr,
680 itemSizes[i].encodedLen,
681 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
682 array->rgItems + i * arrayDesc->itemSize,
683 &itemSizes[i].size, NULL);
684 if (ret)
686 DWORD nextLen;
688 nextData += itemSizes[i].size - arrayDesc->itemSize;
689 ret = CRYPT_GetLen(ptr,
690 cbEncoded - (ptr - pbEncoded), &nextLen);
691 if (ret)
692 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
697 if (itemSizes != &itemSize)
698 CryptMemFree(itemSizes);
701 else
703 SetLastError(CRYPT_E_ASN1_BADTAG);
704 ret = FALSE;
706 return ret;
709 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
710 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
711 * to CRYPT_E_ASN1_CORRUPT.
712 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
713 * set!
715 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
716 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
717 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
719 BOOL ret;
720 DWORD dataLen;
722 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
724 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
725 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
727 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
728 bytesNeeded += 1 + lenBytes + dataLen;
730 if (!pvStructInfo)
731 *pcbStructInfo = bytesNeeded;
732 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
734 CRYPT_DER_BLOB *blob;
736 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
737 pvStructInfo = *(BYTE **)pvStructInfo;
738 blob = (CRYPT_DER_BLOB *)pvStructInfo;
739 blob->cbData = 1 + lenBytes + dataLen;
740 if (blob->cbData)
742 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
743 blob->pbData = (BYTE *)pbEncoded;
744 else
746 assert(blob->pbData);
747 memcpy(blob->pbData, pbEncoded, blob->cbData);
750 else
752 SetLastError(CRYPT_E_ASN1_CORRUPT);
753 ret = FALSE;
757 return ret;
760 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
761 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
762 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
763 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
765 BOOL ret;
767 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
768 pDecodePara, pvStructInfo, *pcbStructInfo);
770 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
771 * place.
773 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
774 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
775 pvStructInfo, pcbStructInfo);
776 if (ret && pvStructInfo)
778 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
780 if (blob->cbData)
782 DWORD i;
783 BYTE temp;
785 for (i = 0; i < blob->cbData / 2; i++)
787 temp = blob->pbData[i];
788 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
789 blob->pbData[blob->cbData - i - 1] = temp;
793 TRACE("returning %d (%08x)\n", ret, GetLastError());
794 return ret;
797 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
798 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
799 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
801 BOOL ret = TRUE;
803 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
804 pDecodePara, pvStructInfo, *pcbStructInfo);
806 __TRY
808 struct AsnDecodeSequenceItem items[] = {
809 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
810 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
811 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
812 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
813 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
814 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
815 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
816 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
817 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
818 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
821 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
822 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
823 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
824 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
825 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
827 __EXCEPT_PAGE_FAULT
829 SetLastError(STATUS_ACCESS_VIOLATION);
830 ret = FALSE;
832 __ENDTRY
834 TRACE("Returning %d (%08x)\n", ret, GetLastError());
835 return ret;
838 /* Internal function */
839 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
840 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
841 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
843 BOOL ret;
844 DWORD dataLen;
846 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
848 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
850 ret = CRYPT_AsnDecodeIntInternal(dwCertEncodingType, NULL,
851 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara, pvStructInfo,
852 pcbStructInfo);
854 return ret;
857 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
858 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
859 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
861 BOOL ret;
863 struct AsnDecodeSequenceItem items[] = {
864 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
865 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
866 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
867 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
870 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
871 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
872 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
873 return ret;
876 /* Internal function */
877 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
878 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
879 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
881 BOOL ret;
882 DWORD dataLen;
884 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
886 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
888 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
889 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
890 pDecodePara, pvStructInfo, pcbStructInfo);
892 return ret;
895 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
896 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
897 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
899 BOOL ret = TRUE;
900 struct AsnDecodeSequenceItem items[] = {
901 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
902 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
903 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
904 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
905 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
906 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
907 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
908 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
909 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
910 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
911 Issuer.pbData) },
912 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
913 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
914 FALSE, 0 },
915 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
916 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
917 Subject.pbData) },
918 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
919 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
920 FALSE, TRUE, offsetof(CERT_INFO,
921 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
922 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
923 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
924 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
925 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
926 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
927 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
928 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
929 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
930 offsetof(CERT_INFO, rgExtension), 0 },
933 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
934 pDecodePara, pvStructInfo, *pcbStructInfo);
936 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
937 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
938 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
939 if (ret && pvStructInfo)
941 CERT_INFO *info;
943 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
944 info = *(CERT_INFO **)pvStructInfo;
945 else
946 info = (CERT_INFO *)pvStructInfo;
947 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
948 !info->Subject.cbData)
950 SetLastError(CRYPT_E_ASN1_CORRUPT);
951 /* Don't need to deallocate, because it should have failed on the
952 * first pass (and no memory was allocated.)
954 ret = FALSE;
958 TRACE("Returning %d (%08x)\n", ret, GetLastError());
959 return ret;
962 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
963 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
964 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
966 BOOL ret = FALSE;
968 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
969 pDecodePara, pvStructInfo, *pcbStructInfo);
971 __TRY
973 DWORD size = 0;
975 /* Unless told not to, first try to decode it as a signed cert. */
976 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
978 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
980 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
981 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
982 (BYTE *)&signedCert, &size);
983 if (ret)
985 size = 0;
986 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
987 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
988 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
989 pvStructInfo, pcbStructInfo);
990 LocalFree(signedCert);
993 /* Failing that, try it as an unsigned cert */
994 if (!ret)
996 size = 0;
997 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
998 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
999 pDecodePara, pvStructInfo, pcbStructInfo);
1002 __EXCEPT_PAGE_FAULT
1004 SetLastError(STATUS_ACCESS_VIOLATION);
1006 __ENDTRY
1008 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1009 return ret;
1012 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1013 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1015 BOOL ret;
1016 struct AsnDecodeSequenceItem items[] = {
1017 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1018 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1019 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1020 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
1021 sizeof(FILETIME), FALSE, FALSE, 0 },
1022 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1023 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1024 offsetof(CRL_ENTRY, rgExtension), 0 },
1026 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1028 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1029 *pcbStructInfo);
1031 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1032 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1033 NULL, entry, pcbStructInfo, pcbDecoded,
1034 entry ? entry->SerialNumber.pbData : NULL);
1035 return ret;
1038 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1039 * been set prior to calling.
1041 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
1042 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1043 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1045 BOOL ret;
1046 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1047 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1048 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1049 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1051 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1052 pDecodePara, pvStructInfo, *pcbStructInfo);
1054 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1055 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
1056 entries ? entries->rgItems : NULL);
1057 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1058 return ret;
1061 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1062 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1063 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1065 struct AsnDecodeSequenceItem items[] = {
1066 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1067 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1068 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1069 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1070 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1071 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1072 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1073 Issuer.pbData) },
1074 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
1075 sizeof(FILETIME), FALSE, FALSE, 0 },
1076 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
1077 sizeof(FILETIME), TRUE, FALSE, 0 },
1078 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1079 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1080 offsetof(CRL_INFO, rgCRLEntry), 0 },
1081 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1082 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1083 offsetof(CRL_INFO, rgExtension), 0 },
1085 BOOL ret = TRUE;
1087 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1088 pDecodePara, pvStructInfo, *pcbStructInfo);
1090 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1091 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1092 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1094 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1095 return ret;
1098 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1099 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1100 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1102 BOOL ret = FALSE;
1104 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1105 pDecodePara, pvStructInfo, *pcbStructInfo);
1107 __TRY
1109 DWORD size = 0;
1111 /* Unless told not to, first try to decode it as a signed crl. */
1112 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1114 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1116 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1117 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1118 (BYTE *)&signedCrl, &size);
1119 if (ret)
1121 size = 0;
1122 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1123 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1124 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1125 pvStructInfo, pcbStructInfo);
1126 LocalFree(signedCrl);
1129 /* Failing that, try it as an unsigned crl */
1130 if (!ret)
1132 size = 0;
1133 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1134 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1135 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1138 __EXCEPT_PAGE_FAULT
1140 SetLastError(STATUS_ACCESS_VIOLATION);
1142 __ENDTRY
1144 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1145 return ret;
1148 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1149 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1151 BOOL ret = TRUE;
1152 DWORD dataLen;
1154 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1155 pvStructInfo, *pcbStructInfo);
1157 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1159 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1160 DWORD bytesNeeded = sizeof(LPSTR);
1162 if (dataLen)
1164 /* The largest possible string for the first two components
1165 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1167 char firstTwo[6];
1168 const BYTE *ptr;
1170 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1171 pbEncoded[1 + lenBytes] / 40,
1172 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1173 * 40);
1174 bytesNeeded += strlen(firstTwo) + 1;
1175 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1176 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1178 /* large enough for ".4000000" */
1179 char str[9];
1180 int val = 0;
1182 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1183 (*ptr & 0x80))
1185 val <<= 7;
1186 val |= *ptr & 0x7f;
1187 ptr++;
1189 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1190 (*ptr & 0x80))
1192 SetLastError(CRYPT_E_ASN1_CORRUPT);
1193 ret = FALSE;
1195 else
1197 val <<= 7;
1198 val |= *ptr++;
1199 snprintf(str, sizeof(str), ".%d", val);
1200 bytesNeeded += strlen(str);
1204 if (pcbDecoded)
1205 *pcbDecoded = 1 + lenBytes + dataLen;
1206 if (!pvStructInfo)
1207 *pcbStructInfo = bytesNeeded;
1208 else if (*pcbStructInfo < bytesNeeded)
1210 *pcbStructInfo = bytesNeeded;
1211 SetLastError(ERROR_MORE_DATA);
1212 ret = FALSE;
1214 else
1216 if (dataLen)
1218 const BYTE *ptr;
1219 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1221 *pszObjId = 0;
1222 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1223 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1224 40) * 40);
1225 pszObjId += strlen(pszObjId);
1226 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1227 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1229 int val = 0;
1231 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1232 (*ptr & 0x80))
1234 val <<= 7;
1235 val |= *ptr & 0x7f;
1236 ptr++;
1238 val <<= 7;
1239 val |= *ptr++;
1240 sprintf(pszObjId, ".%d", val);
1241 pszObjId += strlen(pszObjId);
1244 else
1245 *(LPSTR *)pvStructInfo = NULL;
1246 *pcbStructInfo = bytesNeeded;
1249 return ret;
1252 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTagWrap(DWORD dwCertEncodingType,
1253 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1254 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1256 return CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1257 pvStructInfo, pcbStructInfo, NULL);
1260 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1261 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1263 BOOL ret;
1265 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1266 pvStructInfo, *pcbStructInfo);
1268 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1269 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1270 pvStructInfo, pcbStructInfo, pcbDecoded);
1271 else
1273 SetLastError(CRYPT_E_ASN1_BADTAG);
1274 ret = FALSE;
1276 return ret;
1279 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1280 * ahead of time!
1282 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1283 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1285 struct AsnDecodeSequenceItem items[] = {
1286 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1287 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1288 offsetof(CERT_EXTENSION, pszObjId), 0 },
1289 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1290 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1291 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1292 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1293 offsetof(CERT_EXTENSION, Value.pbData) },
1295 BOOL ret = TRUE;
1296 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1298 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1299 *pcbStructInfo);
1301 if (ext)
1302 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1303 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1304 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1305 ext, pcbStructInfo, pcbDecoded, ext ? ext->pszObjId : NULL);
1306 if (ext)
1307 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1308 debugstr_a(ext->pszObjId));
1309 TRACE("returning %d (%08x)\n", ret, GetLastError());
1310 return ret;
1313 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1314 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1315 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1317 BOOL ret = TRUE;
1318 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1319 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1320 offsetof(CERT_EXTENSION, pszObjId) };
1321 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1323 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1324 pDecodePara, pvStructInfo, *pcbStructInfo);
1326 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1327 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
1328 exts ? exts->rgExtension : NULL);
1329 return ret;
1332 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1333 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1334 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1336 BOOL ret = TRUE;
1338 __TRY
1340 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1341 lpszStructType, pbEncoded, cbEncoded,
1342 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1343 if (ret && pvStructInfo)
1345 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1346 pcbStructInfo, *pcbStructInfo);
1347 if (ret)
1349 CERT_EXTENSIONS *exts;
1351 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1352 pvStructInfo = *(BYTE **)pvStructInfo;
1353 exts = (CERT_EXTENSIONS *)pvStructInfo;
1354 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1355 sizeof(CERT_EXTENSIONS));
1356 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1357 lpszStructType, pbEncoded, cbEncoded,
1358 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1359 pcbStructInfo);
1363 __EXCEPT_PAGE_FAULT
1365 SetLastError(STATUS_ACCESS_VIOLATION);
1366 ret = FALSE;
1368 __ENDTRY
1369 return ret;
1372 /* Warning: this assumes the address of value->Value.pbData is already set, in
1373 * order to avoid overwriting memory. (In some cases, it may change it, if it
1374 * doesn't copy anything to memory.) Be sure to set it correctly!
1376 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1377 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1378 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1380 BOOL ret = TRUE;
1381 DWORD dataLen;
1382 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1384 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1386 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1387 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1389 switch (pbEncoded[0])
1391 case ASN_OCTETSTRING:
1392 valueType = CERT_RDN_OCTET_STRING;
1393 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1394 bytesNeeded += dataLen;
1395 break;
1396 case ASN_NUMERICSTRING:
1397 valueType = CERT_RDN_NUMERIC_STRING;
1398 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1399 bytesNeeded += dataLen;
1400 break;
1401 case ASN_PRINTABLESTRING:
1402 valueType = CERT_RDN_PRINTABLE_STRING;
1403 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1404 bytesNeeded += dataLen;
1405 break;
1406 case ASN_IA5STRING:
1407 valueType = CERT_RDN_IA5_STRING;
1408 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1409 bytesNeeded += dataLen;
1410 break;
1411 case ASN_T61STRING:
1412 valueType = CERT_RDN_T61_STRING;
1413 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1414 bytesNeeded += dataLen;
1415 break;
1416 case ASN_VIDEOTEXSTRING:
1417 valueType = CERT_RDN_VIDEOTEX_STRING;
1418 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1419 bytesNeeded += dataLen;
1420 break;
1421 case ASN_GRAPHICSTRING:
1422 valueType = CERT_RDN_GRAPHIC_STRING;
1423 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1424 bytesNeeded += dataLen;
1425 break;
1426 case ASN_VISIBLESTRING:
1427 valueType = CERT_RDN_VISIBLE_STRING;
1428 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1429 bytesNeeded += dataLen;
1430 break;
1431 case ASN_GENERALSTRING:
1432 valueType = CERT_RDN_GENERAL_STRING;
1433 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1434 bytesNeeded += dataLen;
1435 break;
1436 case ASN_UNIVERSALSTRING:
1437 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1438 SetLastError(CRYPT_E_ASN1_BADTAG);
1439 return FALSE;
1440 case ASN_BMPSTRING:
1441 valueType = CERT_RDN_BMP_STRING;
1442 bytesNeeded += dataLen;
1443 break;
1444 case ASN_UTF8STRING:
1445 valueType = CERT_RDN_UTF8_STRING;
1446 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1447 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1448 break;
1449 default:
1450 SetLastError(CRYPT_E_ASN1_BADTAG);
1451 return FALSE;
1454 if (!value)
1455 *pcbStructInfo = bytesNeeded;
1456 else if (*pcbStructInfo < bytesNeeded)
1458 *pcbStructInfo = bytesNeeded;
1459 SetLastError(ERROR_MORE_DATA);
1460 ret = FALSE;
1462 else
1464 *pcbStructInfo = bytesNeeded;
1465 value->dwValueType = valueType;
1466 if (dataLen)
1468 DWORD i;
1470 assert(value->Value.pbData);
1471 switch (pbEncoded[0])
1473 case ASN_OCTETSTRING:
1474 case ASN_NUMERICSTRING:
1475 case ASN_PRINTABLESTRING:
1476 case ASN_IA5STRING:
1477 case ASN_T61STRING:
1478 case ASN_VIDEOTEXSTRING:
1479 case ASN_GRAPHICSTRING:
1480 case ASN_VISIBLESTRING:
1481 case ASN_GENERALSTRING:
1482 value->Value.cbData = dataLen;
1483 if (dataLen)
1485 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1486 memcpy(value->Value.pbData,
1487 pbEncoded + 1 + lenBytes, dataLen);
1488 else
1489 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1490 lenBytes;
1492 break;
1493 case ASN_BMPSTRING:
1495 LPWSTR str = (LPWSTR)value->Value.pbData;
1497 value->Value.cbData = dataLen;
1498 for (i = 0; i < dataLen / 2; i++)
1499 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1500 pbEncoded[1 + lenBytes + 2 * i + 1];
1501 break;
1503 case ASN_UTF8STRING:
1505 LPWSTR str = (LPWSTR)value->Value.pbData;
1507 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1508 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1509 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1510 break;
1514 else
1516 value->Value.cbData = 0;
1517 value->Value.pbData = NULL;
1521 return ret;
1524 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1525 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1526 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1528 BOOL ret = TRUE;
1530 __TRY
1532 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1533 lpszStructType, pbEncoded, cbEncoded,
1534 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1535 if (ret && pvStructInfo)
1537 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1538 pcbStructInfo, *pcbStructInfo);
1539 if (ret)
1541 CERT_NAME_VALUE *value;
1543 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1544 pvStructInfo = *(BYTE **)pvStructInfo;
1545 value = (CERT_NAME_VALUE *)pvStructInfo;
1546 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1547 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1548 lpszStructType, pbEncoded, cbEncoded,
1549 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1550 pcbStructInfo);
1554 __EXCEPT_PAGE_FAULT
1556 SetLastError(STATUS_ACCESS_VIOLATION);
1557 ret = FALSE;
1559 __ENDTRY
1560 return ret;
1563 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1564 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1565 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1566 void *pvStructInfo, DWORD *pcbStructInfo)
1568 BOOL ret = TRUE;
1569 DWORD dataLen;
1570 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1572 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1574 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1575 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1577 switch (pbEncoded[0])
1579 case ASN_NUMERICSTRING:
1580 valueType = CERT_RDN_NUMERIC_STRING;
1581 bytesNeeded += dataLen * 2;
1582 break;
1583 case ASN_PRINTABLESTRING:
1584 valueType = CERT_RDN_PRINTABLE_STRING;
1585 bytesNeeded += dataLen * 2;
1586 break;
1587 case ASN_IA5STRING:
1588 valueType = CERT_RDN_IA5_STRING;
1589 bytesNeeded += dataLen * 2;
1590 break;
1591 case ASN_T61STRING:
1592 valueType = CERT_RDN_T61_STRING;
1593 bytesNeeded += dataLen * 2;
1594 break;
1595 case ASN_VIDEOTEXSTRING:
1596 valueType = CERT_RDN_VIDEOTEX_STRING;
1597 bytesNeeded += dataLen * 2;
1598 break;
1599 case ASN_GRAPHICSTRING:
1600 valueType = CERT_RDN_GRAPHIC_STRING;
1601 bytesNeeded += dataLen * 2;
1602 break;
1603 case ASN_VISIBLESTRING:
1604 valueType = CERT_RDN_VISIBLE_STRING;
1605 bytesNeeded += dataLen * 2;
1606 break;
1607 case ASN_GENERALSTRING:
1608 valueType = CERT_RDN_GENERAL_STRING;
1609 bytesNeeded += dataLen * 2;
1610 break;
1611 case ASN_UNIVERSALSTRING:
1612 valueType = CERT_RDN_UNIVERSAL_STRING;
1613 bytesNeeded += dataLen / 2;
1614 break;
1615 case ASN_BMPSTRING:
1616 valueType = CERT_RDN_BMP_STRING;
1617 bytesNeeded += dataLen;
1618 break;
1619 case ASN_UTF8STRING:
1620 valueType = CERT_RDN_UTF8_STRING;
1621 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1622 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1623 break;
1624 default:
1625 SetLastError(CRYPT_E_ASN1_BADTAG);
1626 return FALSE;
1629 if (!value)
1630 *pcbStructInfo = bytesNeeded;
1631 else if (*pcbStructInfo < bytesNeeded)
1633 *pcbStructInfo = bytesNeeded;
1634 SetLastError(ERROR_MORE_DATA);
1635 ret = FALSE;
1637 else
1639 *pcbStructInfo = bytesNeeded;
1640 value->dwValueType = valueType;
1641 if (dataLen)
1643 DWORD i;
1644 LPWSTR str = (LPWSTR)value->Value.pbData;
1646 assert(value->Value.pbData);
1647 switch (pbEncoded[0])
1649 case ASN_NUMERICSTRING:
1650 case ASN_PRINTABLESTRING:
1651 case ASN_IA5STRING:
1652 case ASN_T61STRING:
1653 case ASN_VIDEOTEXSTRING:
1654 case ASN_GRAPHICSTRING:
1655 case ASN_VISIBLESTRING:
1656 case ASN_GENERALSTRING:
1657 value->Value.cbData = dataLen * 2;
1658 for (i = 0; i < dataLen; i++)
1659 str[i] = pbEncoded[1 + lenBytes + i];
1660 break;
1661 case ASN_UNIVERSALSTRING:
1662 value->Value.cbData = dataLen / 2;
1663 for (i = 0; i < dataLen / 4; i++)
1664 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1665 | pbEncoded[1 + lenBytes + 2 * i + 3];
1666 break;
1667 case ASN_BMPSTRING:
1668 value->Value.cbData = dataLen;
1669 for (i = 0; i < dataLen / 2; i++)
1670 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1671 pbEncoded[1 + lenBytes + 2 * i + 1];
1672 break;
1673 case ASN_UTF8STRING:
1674 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1675 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1676 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1677 break;
1680 else
1682 value->Value.cbData = 0;
1683 value->Value.pbData = NULL;
1687 return ret;
1690 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1691 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1692 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1694 BOOL ret = TRUE;
1696 __TRY
1698 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1699 lpszStructType, pbEncoded, cbEncoded,
1700 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1701 if (ret && pvStructInfo)
1703 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1704 pcbStructInfo, *pcbStructInfo);
1705 if (ret)
1707 CERT_NAME_VALUE *value;
1709 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1710 pvStructInfo = *(BYTE **)pvStructInfo;
1711 value = (CERT_NAME_VALUE *)pvStructInfo;
1712 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1713 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1714 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1715 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1716 pcbStructInfo);
1720 __EXCEPT_PAGE_FAULT
1722 SetLastError(STATUS_ACCESS_VIOLATION);
1723 ret = FALSE;
1725 __ENDTRY
1726 return ret;
1729 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1730 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1732 BOOL ret;
1733 struct AsnDecodeSequenceItem items[] = {
1734 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1735 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1736 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1737 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1738 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1739 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1741 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1743 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1744 pvStructInfo, *pcbStructInfo);
1746 if (attr)
1747 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1748 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1749 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1750 attr, pcbStructInfo, pcbDecoded, attr ? attr->pszObjId : NULL);
1751 if (attr)
1753 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1754 debugstr_a(attr->pszObjId));
1755 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1757 TRACE("returning %d (%08x)\n", ret, GetLastError());
1758 return ret;
1761 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1762 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1764 BOOL ret = TRUE;
1765 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1766 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1767 offsetof(CERT_RDN_ATTR, pszObjId) };
1768 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1770 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1771 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1772 rdn ? rdn->rgRDNAttr : NULL);
1773 return ret;
1776 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1777 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1778 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1780 BOOL ret = TRUE;
1782 __TRY
1784 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1785 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1786 offsetof(CERT_RDN, rgRDNAttr) };
1788 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1789 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1791 __EXCEPT_PAGE_FAULT
1793 SetLastError(STATUS_ACCESS_VIOLATION);
1794 ret = FALSE;
1796 __ENDTRY
1797 return ret;
1800 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1801 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1802 DWORD *pcbDecoded)
1804 BOOL ret;
1805 struct AsnDecodeSequenceItem items[] = {
1806 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1807 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1808 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1809 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1810 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1811 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1813 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1815 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1816 pvStructInfo, *pcbStructInfo);
1818 if (attr)
1819 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1820 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1821 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1822 attr, pcbStructInfo, pcbDecoded, attr ? attr->pszObjId : NULL);
1823 if (attr)
1825 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1826 debugstr_a(attr->pszObjId));
1827 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1829 TRACE("returning %d (%08x)\n", ret, GetLastError());
1830 return ret;
1833 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1834 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1836 BOOL ret = TRUE;
1837 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1838 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1839 offsetof(CERT_RDN_ATTR, pszObjId) };
1840 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1842 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1843 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1844 rdn ? rdn->rgRDNAttr : NULL);
1845 return ret;
1848 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1849 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1850 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1852 BOOL ret = TRUE;
1854 __TRY
1856 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1857 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1858 offsetof(CERT_RDN, rgRDNAttr) };
1860 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1861 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1863 __EXCEPT_PAGE_FAULT
1865 SetLastError(STATUS_ACCESS_VIOLATION);
1866 ret = FALSE;
1868 __ENDTRY
1869 return ret;
1872 static BOOL CRYPT_AsnDecodeCopyBytesInternal(const BYTE *pbEncoded,
1873 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1874 DWORD *pcbDecoded)
1876 BOOL ret = TRUE;
1877 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1879 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1880 pvStructInfo, *pcbStructInfo);
1882 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1883 bytesNeeded += cbEncoded;
1884 if (pcbDecoded)
1885 *pcbDecoded = cbEncoded;
1886 if (!pvStructInfo)
1887 *pcbStructInfo = bytesNeeded;
1888 else if (*pcbStructInfo < bytesNeeded)
1890 SetLastError(ERROR_MORE_DATA);
1891 *pcbStructInfo = bytesNeeded;
1892 ret = FALSE;
1894 else
1896 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1898 *pcbStructInfo = bytesNeeded;
1899 blob->cbData = cbEncoded;
1900 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1901 blob->pbData = (LPBYTE)pbEncoded;
1902 else
1904 assert(blob->pbData);
1905 memcpy(blob->pbData, pbEncoded, blob->cbData);
1908 return ret;
1911 static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType,
1912 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1913 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1915 BOOL ret;
1916 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytesInternal,
1917 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1918 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1920 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1921 pDecodePara, pvStructInfo, *pcbStructInfo);
1923 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1924 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
1925 array ? array->rgItems : NULL);
1926 return ret;
1929 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
1930 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1931 DWORD *pcbDecoded)
1933 BOOL ret;
1934 struct AsnDecodeSequenceItem items[] = {
1935 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1936 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1937 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1938 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1939 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1940 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1942 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1944 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1945 pvStructInfo, *pcbStructInfo);
1947 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1948 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1949 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1950 attr ? attr->pszObjId : NULL);
1951 TRACE("returning %d\n", ret);
1952 return ret;
1955 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1956 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1957 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1959 BOOL ret = FALSE;
1961 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1962 pDecodePara, pvStructInfo, *pcbStructInfo);
1964 __TRY
1966 DWORD bytesNeeded;
1968 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
1969 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
1970 if (ret)
1972 if (!pvStructInfo)
1973 *pcbStructInfo = bytesNeeded;
1974 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1975 pvStructInfo, pcbStructInfo, bytesNeeded)))
1977 PCRYPT_ATTRIBUTE attr;
1979 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1980 pvStructInfo = *(BYTE **)pvStructInfo;
1981 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1982 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
1983 sizeof(CRYPT_ATTRIBUTE));
1984 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
1985 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
1986 NULL);
1990 __EXCEPT_PAGE_FAULT
1992 SetLastError(STATUS_ACCESS_VIOLATION);
1994 __ENDTRY
1995 TRACE("returning %d\n", ret);
1996 return ret;
1999 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal(
2000 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2001 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2002 void *pvStructInfo, DWORD *pcbStructInfo)
2004 struct AsnArrayDescriptor arrayDesc = { 0,
2005 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2006 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2007 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2008 BOOL ret;
2010 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2011 pDecodePara, pvStructInfo, pcbStructInfo, NULL, attrs ? attrs->rgAttr :
2012 NULL);
2013 return ret;
2016 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2017 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2018 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2020 BOOL ret = FALSE;
2022 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2023 pDecodePara, pvStructInfo, *pcbStructInfo);
2025 __TRY
2027 DWORD bytesNeeded;
2029 if (!cbEncoded)
2030 SetLastError(CRYPT_E_ASN1_EOD);
2031 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2032 SetLastError(CRYPT_E_ASN1_CORRUPT);
2033 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(
2034 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
2035 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2037 if (!pvStructInfo)
2038 *pcbStructInfo = bytesNeeded;
2039 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2040 pvStructInfo, pcbStructInfo, bytesNeeded)))
2042 PCRYPT_ATTRIBUTES attrs;
2044 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2045 pvStructInfo = *(BYTE **)pvStructInfo;
2046 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2047 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2048 sizeof(CRYPT_ATTRIBUTES));
2049 ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
2050 lpszStructType, pbEncoded, cbEncoded,
2051 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2052 &bytesNeeded);
2056 __EXCEPT_PAGE_FAULT
2058 SetLastError(STATUS_ACCESS_VIOLATION);
2060 __ENDTRY
2061 TRACE("returning %d\n", ret);
2062 return ret;
2065 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
2066 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2067 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2069 BOOL ret = TRUE;
2070 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
2072 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2073 pDecodePara, pvStructInfo, *pcbStructInfo);
2075 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2076 bytesNeeded += cbEncoded;
2077 if (!pvStructInfo)
2078 *pcbStructInfo = bytesNeeded;
2079 else if (*pcbStructInfo < bytesNeeded)
2081 SetLastError(ERROR_MORE_DATA);
2082 *pcbStructInfo = bytesNeeded;
2083 ret = FALSE;
2085 else
2087 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
2089 *pcbStructInfo = bytesNeeded;
2090 blob->cbData = cbEncoded;
2091 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2092 blob->pbData = (LPBYTE)pbEncoded;
2093 else
2095 assert(blob->pbData);
2096 memcpy(blob->pbData, pbEncoded, blob->cbData);
2099 return ret;
2102 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
2103 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2104 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2106 CRYPT_ALGORITHM_IDENTIFIER *algo =
2107 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2108 BOOL ret = TRUE;
2109 struct AsnDecodeSequenceItem items[] = {
2110 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2111 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
2112 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2113 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2114 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2115 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2118 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2119 pDecodePara, pvStructInfo, *pcbStructInfo);
2121 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2122 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2123 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2124 algo ? algo->pszObjId : NULL);
2125 if (ret && pvStructInfo)
2127 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2128 debugstr_a(algo->pszObjId));
2130 return ret;
2133 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
2134 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2135 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2137 BOOL ret = TRUE;
2138 struct AsnDecodeSequenceItem items[] = {
2139 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2140 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2141 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2142 Algorithm.pszObjId) },
2143 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2144 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2145 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2147 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2149 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2150 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2151 pDecodePara, pvStructInfo, pcbStructInfo, NULL, info ?
2152 info->Algorithm.Parameters.pbData : NULL);
2153 return ret;
2156 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2157 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2158 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2160 BOOL ret = TRUE;
2162 __TRY
2164 DWORD bytesNeeded;
2166 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2167 lpszStructType, pbEncoded, cbEncoded,
2168 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2170 if (!pvStructInfo)
2171 *pcbStructInfo = bytesNeeded;
2172 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2173 pvStructInfo, pcbStructInfo, bytesNeeded)))
2175 PCERT_PUBLIC_KEY_INFO info;
2177 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2178 pvStructInfo = *(BYTE **)pvStructInfo;
2179 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2180 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2181 sizeof(CERT_PUBLIC_KEY_INFO);
2182 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2183 lpszStructType, pbEncoded, cbEncoded,
2184 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2185 &bytesNeeded);
2189 __EXCEPT_PAGE_FAULT
2191 SetLastError(STATUS_ACCESS_VIOLATION);
2192 ret = FALSE;
2194 __ENDTRY
2195 return ret;
2198 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2199 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2200 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2202 BOOL ret;
2204 if (cbEncoded < 3)
2206 SetLastError(CRYPT_E_ASN1_CORRUPT);
2207 return FALSE;
2209 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2211 SetLastError(CRYPT_E_ASN1_CORRUPT);
2212 return FALSE;
2214 if (pbEncoded[1] > 1)
2216 SetLastError(CRYPT_E_ASN1_CORRUPT);
2217 return FALSE;
2219 if (!pvStructInfo)
2221 *pcbStructInfo = sizeof(BOOL);
2222 ret = TRUE;
2224 else if (*pcbStructInfo < sizeof(BOOL))
2226 *pcbStructInfo = sizeof(BOOL);
2227 SetLastError(ERROR_MORE_DATA);
2228 ret = FALSE;
2230 else
2232 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2233 ret = TRUE;
2235 TRACE("returning %d (%08x)\n", ret, GetLastError());
2236 return ret;
2239 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2240 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2242 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2243 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2244 BOOL ret;
2246 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2247 pvStructInfo, *pcbStructInfo);
2249 if (cbEncoded < 2)
2251 SetLastError(CRYPT_E_ASN1_CORRUPT);
2252 return FALSE;
2254 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2255 if (1 + lenBytes > cbEncoded)
2257 SetLastError(CRYPT_E_ASN1_CORRUPT);
2258 return FALSE;
2260 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2262 switch (pbEncoded[0] & ASN_TYPE_MASK)
2264 case 1: /* rfc822Name */
2265 case 2: /* dNSName */
2266 case 6: /* uniformResourceIdentifier */
2267 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2268 break;
2269 case 4: /* directoryName */
2270 case 7: /* iPAddress */
2271 bytesNeeded += dataLen;
2272 break;
2273 case 8: /* registeredID */
2274 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2275 &dataLen, NULL);
2276 if (ret)
2278 /* FIXME: ugly, shouldn't need to know internals of OID decode
2279 * function to use it.
2281 bytesNeeded += dataLen - sizeof(LPSTR);
2283 break;
2284 case 0: /* otherName */
2285 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2286 SetLastError(CRYPT_E_ASN1_BADTAG);
2287 ret = FALSE;
2288 break;
2289 case 3: /* x400Address, unimplemented */
2290 case 5: /* ediPartyName, unimplemented */
2291 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2292 SetLastError(CRYPT_E_ASN1_BADTAG);
2293 ret = FALSE;
2294 break;
2295 default:
2296 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2297 SetLastError(CRYPT_E_ASN1_CORRUPT);
2298 ret = FALSE;
2300 if (ret)
2302 if (pcbDecoded)
2303 *pcbDecoded = 1 + lenBytes + dataLen;
2304 if (!entry)
2305 *pcbStructInfo = bytesNeeded;
2306 else if (*pcbStructInfo < bytesNeeded)
2308 *pcbStructInfo = bytesNeeded;
2309 SetLastError(ERROR_MORE_DATA);
2310 ret = FALSE;
2312 else
2314 *pcbStructInfo = bytesNeeded;
2315 /* MS used values one greater than the asn1 ones.. sigh */
2316 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2317 switch (pbEncoded[0] & ASN_TYPE_MASK)
2319 case 1: /* rfc822Name */
2320 case 2: /* dNSName */
2321 case 6: /* uniformResourceIdentifier */
2323 DWORD i;
2325 for (i = 0; i < dataLen; i++)
2326 entry->u.pwszURL[i] =
2327 (WCHAR)pbEncoded[1 + lenBytes + i];
2328 entry->u.pwszURL[i] = 0;
2329 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2330 debugstr_w(entry->u.pwszURL));
2331 break;
2333 case 4: /* directoryName */
2334 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2335 /* The data are memory-equivalent with the IPAddress case,
2336 * fall-through
2338 case 7: /* iPAddress */
2339 /* The next data pointer is in the pwszURL spot, that is,
2340 * the first 4 bytes. Need to move it to the next spot.
2342 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2343 entry->u.IPAddress.cbData = dataLen;
2344 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2345 dataLen);
2346 break;
2347 case 8: /* registeredID */
2348 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2349 &entry->u.pszRegisteredID, &dataLen, NULL);
2350 break;
2355 return ret;
2358 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2359 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2360 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2362 BOOL ret = TRUE;
2363 struct AsnArrayDescriptor arrayDesc = { 0,
2364 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2365 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2366 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2368 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2369 pDecodePara, pvStructInfo, *pcbStructInfo);
2371 if (info)
2372 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2373 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2374 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2375 info ? info->rgAltEntry : NULL);
2376 return ret;
2379 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2380 static BOOL WINAPI CRYPT_AsnDecodeIntegerSwapBytes(DWORD dwCertEncodingType,
2381 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2382 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2384 BOOL ret;
2386 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2387 pDecodePara, pvStructInfo, *pcbStructInfo);
2389 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2390 * place.
2392 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType, lpszStructType,
2393 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
2394 pvStructInfo, pcbStructInfo);
2395 if (ret && pvStructInfo)
2397 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2399 if (blob->cbData)
2401 DWORD i;
2402 BYTE temp;
2404 for (i = 0; i < blob->cbData / 2; i++)
2406 temp = blob->pbData[i];
2407 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2408 blob->pbData[blob->cbData - i - 1] = temp;
2412 TRACE("returning %d (%08x)\n", ret, GetLastError());
2413 return ret;
2416 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2417 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2418 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2420 BOOL ret;
2422 __TRY
2424 struct AsnDecodeSequenceItem items[] = {
2425 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2426 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2427 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2428 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2429 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2430 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2431 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2432 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2433 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2434 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2435 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2438 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2439 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2440 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2442 __EXCEPT_PAGE_FAULT
2444 SetLastError(STATUS_ACCESS_VIOLATION);
2445 ret = FALSE;
2447 __ENDTRY
2448 return ret;
2451 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2452 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2453 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2455 BOOL ret;
2457 __TRY
2459 struct AsnDecodeSequenceItem items[] = {
2460 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2461 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2462 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2463 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2464 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2465 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2466 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2467 AuthorityCertIssuer.rgAltEntry), 0 },
2468 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2469 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2470 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2471 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2472 AuthorityCertSerialNumber.pbData), 0 },
2475 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2476 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2477 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2479 __EXCEPT_PAGE_FAULT
2481 SetLastError(STATUS_ACCESS_VIOLATION);
2482 ret = FALSE;
2484 __ENDTRY
2485 return ret;
2488 static BOOL WINAPI CRYPT_AsnDecodePKCSContent(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 DWORD dataLen;
2495 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2496 pDecodePara, pvStructInfo, *pcbStructInfo);
2498 /* The caller has already checked the tag, no need to check it again.
2499 * Check the outer length is valid by calling CRYPT_GetLen:
2501 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2503 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2504 DWORD innerLen;
2506 pbEncoded += 1 + lenBytes;
2507 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2508 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2510 ret = CRYPT_AsnDecodeCopyBytes(dwCertEncodingType, NULL,
2511 pbEncoded, dataLen, dwFlags, pDecodePara, pvStructInfo,
2512 pcbStructInfo);
2515 return ret;
2518 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfoInternal(
2519 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2520 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2521 void *pvStructInfo, DWORD *pcbStructInfo)
2523 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2524 struct AsnDecodeSequenceItem items[] = {
2525 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2526 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
2527 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2528 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2529 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2530 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2531 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2533 BOOL ret;
2535 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2536 pDecodePara, pvStructInfo, *pcbStructInfo);
2538 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2539 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2540 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2541 info ? info->pszObjId : NULL);
2542 return ret;
2545 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2546 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2547 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2549 BOOL ret = FALSE;
2551 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2552 pDecodePara, pvStructInfo, *pcbStructInfo);
2554 __TRY
2556 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2557 lpszStructType, pbEncoded, cbEncoded,
2558 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
2559 if (ret && pvStructInfo)
2561 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2562 pcbStructInfo, *pcbStructInfo);
2563 if (ret)
2565 CRYPT_CONTENT_INFO *info;
2567 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2568 pvStructInfo = *(BYTE **)pvStructInfo;
2569 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2570 info->pszObjId = (LPSTR)((BYTE *)info +
2571 sizeof(CRYPT_CONTENT_INFO));
2572 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2573 lpszStructType, pbEncoded, cbEncoded,
2574 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2575 pcbStructInfo);
2579 __EXCEPT_PAGE_FAULT
2581 SetLastError(STATUS_ACCESS_VIOLATION);
2583 __ENDTRY
2584 return ret;
2587 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2588 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2589 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2591 BOOL ret;
2592 struct AsnDecodeSequenceItem items[] = {
2593 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2594 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2595 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2596 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2597 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2598 0 },
2599 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2600 CRYPT_AsnDecodePKCSContentInfoInternal,
2601 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2602 ContentInfo.pszObjId), 0 },
2603 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2604 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2605 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2608 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
2609 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2610 pDecodePara, digestedData, pcbDigestedData, NULL, NULL);
2611 return ret;
2614 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2615 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2616 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2618 BOOL ret = TRUE;
2620 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2621 pDecodePara, pvStructInfo, *pcbStructInfo);
2623 __TRY
2625 DWORD bytesNeeded;
2627 if ((ret = CRYPT_AsnDecodeAltNameInternal(dwCertEncodingType,
2628 lpszStructType, pbEncoded, cbEncoded,
2629 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2631 if (!pvStructInfo)
2632 *pcbStructInfo = bytesNeeded;
2633 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2634 pvStructInfo, pcbStructInfo, bytesNeeded)))
2636 CERT_ALT_NAME_INFO *name;
2638 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2639 pvStructInfo = *(BYTE **)pvStructInfo;
2640 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2641 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2642 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2643 ret = CRYPT_AsnDecodeAltNameInternal(dwCertEncodingType,
2644 lpszStructType, pbEncoded, cbEncoded,
2645 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2646 &bytesNeeded);
2650 __EXCEPT_PAGE_FAULT
2652 SetLastError(STATUS_ACCESS_VIOLATION);
2653 ret = FALSE;
2655 __ENDTRY
2656 return ret;
2659 struct PATH_LEN_CONSTRAINT
2661 BOOL fPathLenConstraint;
2662 DWORD dwPathLenConstraint;
2665 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2666 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2667 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2669 BOOL ret = TRUE;
2671 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2672 pvStructInfo, *pcbStructInfo);
2674 if (cbEncoded)
2676 if (pbEncoded[0] == ASN_INTEGER)
2678 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2680 if (!pvStructInfo)
2681 *pcbStructInfo = bytesNeeded;
2682 else if (*pcbStructInfo < bytesNeeded)
2684 SetLastError(ERROR_MORE_DATA);
2685 *pcbStructInfo = bytesNeeded;
2686 ret = FALSE;
2688 else
2690 struct PATH_LEN_CONSTRAINT *constraint =
2691 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2692 DWORD size = sizeof(constraint->dwPathLenConstraint);
2694 ret = CRYPT_AsnDecodeIntInternal(dwCertEncodingType, NULL,
2695 pbEncoded, cbEncoded, dwFlags, pDecodePara,
2696 &constraint->dwPathLenConstraint, &size);
2697 if (ret)
2698 constraint->fPathLenConstraint = TRUE;
2699 TRACE("got an int, dwPathLenConstraint is %d\n",
2700 constraint->dwPathLenConstraint);
2703 else
2705 SetLastError(CRYPT_E_ASN1_CORRUPT);
2706 ret = FALSE;
2709 TRACE("returning %d (%08x)\n", ret, GetLastError());
2710 return ret;
2713 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2714 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2715 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2717 BOOL ret;
2718 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2719 CRYPT_AsnDecodeCopyBytesInternal, sizeof(CERT_NAME_BLOB), TRUE,
2720 offsetof(CERT_NAME_BLOB, pbData) };
2721 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2723 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2724 pDecodePara, pvStructInfo, *pcbStructInfo);
2726 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2727 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2728 entries ? entries->rgItems : NULL);
2729 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2730 return ret;
2733 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2734 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2735 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2737 BOOL ret;
2739 __TRY
2741 struct AsnDecodeSequenceItem items[] = {
2742 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2743 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2744 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2745 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2746 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2747 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2748 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2749 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2750 sizeof(struct GenericArray), TRUE, TRUE,
2751 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2754 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2755 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2756 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2758 __EXCEPT_PAGE_FAULT
2760 SetLastError(STATUS_ACCESS_VIOLATION);
2761 ret = FALSE;
2763 __ENDTRY
2764 return ret;
2767 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2768 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2769 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2771 BOOL ret;
2773 __TRY
2775 struct AsnDecodeSequenceItem items[] = {
2776 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2777 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2778 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2779 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2780 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2783 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2784 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2785 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2787 __EXCEPT_PAGE_FAULT
2789 SetLastError(STATUS_ACCESS_VIOLATION);
2790 ret = FALSE;
2792 __ENDTRY
2793 return ret;
2796 #define RSA1_MAGIC 0x31415352
2798 struct DECODED_RSA_PUB_KEY
2800 DWORD pubexp;
2801 CRYPT_INTEGER_BLOB modulus;
2804 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2805 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2806 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2808 BOOL ret;
2810 __TRY
2812 struct AsnDecodeSequenceItem items[] = {
2813 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2814 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2815 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2816 0 },
2817 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2818 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2820 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2821 DWORD size = 0;
2823 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2824 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2825 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL, NULL);
2826 if (ret)
2828 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2829 decodedKey->modulus.cbData;
2831 if (!pvStructInfo)
2833 *pcbStructInfo = bytesNeeded;
2834 ret = TRUE;
2836 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2837 pvStructInfo, pcbStructInfo, bytesNeeded)))
2839 BLOBHEADER *hdr;
2840 RSAPUBKEY *rsaPubKey;
2842 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2843 pvStructInfo = *(BYTE **)pvStructInfo;
2844 hdr = (BLOBHEADER *)pvStructInfo;
2845 hdr->bType = PUBLICKEYBLOB;
2846 hdr->bVersion = CUR_BLOB_VERSION;
2847 hdr->reserved = 0;
2848 hdr->aiKeyAlg = CALG_RSA_KEYX;
2849 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2850 sizeof(BLOBHEADER));
2851 rsaPubKey->magic = RSA1_MAGIC;
2852 rsaPubKey->pubexp = decodedKey->pubexp;
2853 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2854 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2855 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2856 decodedKey->modulus.cbData);
2858 LocalFree(decodedKey);
2861 __EXCEPT_PAGE_FAULT
2863 SetLastError(STATUS_ACCESS_VIOLATION);
2864 ret = FALSE;
2866 __ENDTRY
2867 return ret;
2870 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2871 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2872 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2874 BOOL ret;
2875 DWORD bytesNeeded, dataLen;
2877 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2878 pDecodePara, pvStructInfo, *pcbStructInfo);
2880 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2882 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2883 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2884 else
2885 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2886 if (!pvStructInfo)
2887 *pcbStructInfo = bytesNeeded;
2888 else if (*pcbStructInfo < bytesNeeded)
2890 SetLastError(ERROR_MORE_DATA);
2891 *pcbStructInfo = bytesNeeded;
2892 ret = FALSE;
2894 else
2896 CRYPT_DATA_BLOB *blob;
2897 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2899 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2900 blob->cbData = dataLen;
2901 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2902 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2903 else
2905 assert(blob->pbData);
2906 if (blob->cbData)
2907 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2908 blob->cbData);
2912 return ret;
2915 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2916 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2917 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2919 BOOL ret;
2921 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2922 pDecodePara, pvStructInfo, *pcbStructInfo);
2924 __TRY
2926 DWORD bytesNeeded;
2928 if (!cbEncoded)
2930 SetLastError(CRYPT_E_ASN1_CORRUPT);
2931 ret = FALSE;
2933 else if (pbEncoded[0] != ASN_OCTETSTRING)
2935 SetLastError(CRYPT_E_ASN1_BADTAG);
2936 ret = FALSE;
2938 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2939 lpszStructType, pbEncoded, cbEncoded,
2940 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2942 if (!pvStructInfo)
2943 *pcbStructInfo = bytesNeeded;
2944 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2945 pvStructInfo, pcbStructInfo, bytesNeeded)))
2947 CRYPT_DATA_BLOB *blob;
2949 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2950 pvStructInfo = *(BYTE **)pvStructInfo;
2951 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2952 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2953 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2954 lpszStructType, pbEncoded, cbEncoded,
2955 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2956 &bytesNeeded);
2960 __EXCEPT_PAGE_FAULT
2962 SetLastError(STATUS_ACCESS_VIOLATION);
2963 ret = FALSE;
2965 __ENDTRY
2966 return ret;
2969 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2970 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2971 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2973 BOOL ret;
2975 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2976 pDecodePara, pvStructInfo, *pcbStructInfo);
2978 if (pbEncoded[0] == ASN_BITSTRING)
2980 DWORD bytesNeeded, dataLen;
2982 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2984 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2985 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2986 else
2987 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2988 if (!pvStructInfo)
2989 *pcbStructInfo = bytesNeeded;
2990 else if (*pcbStructInfo < bytesNeeded)
2992 *pcbStructInfo = bytesNeeded;
2993 SetLastError(ERROR_MORE_DATA);
2994 ret = FALSE;
2996 else
2998 CRYPT_BIT_BLOB *blob;
3000 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3001 blob->cbData = dataLen - 1;
3002 blob->cUnusedBits = *(pbEncoded + 1 +
3003 GET_LEN_BYTES(pbEncoded[1]));
3004 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3006 blob->pbData = (BYTE *)pbEncoded + 2 +
3007 GET_LEN_BYTES(pbEncoded[1]);
3009 else
3011 assert(blob->pbData);
3012 if (blob->cbData)
3014 BYTE mask = 0xff << blob->cUnusedBits;
3016 memcpy(blob->pbData, pbEncoded + 2 +
3017 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
3018 blob->pbData[blob->cbData - 1] &= mask;
3024 else
3026 SetLastError(CRYPT_E_ASN1_BADTAG);
3027 ret = FALSE;
3029 TRACE("returning %d (%08x)\n", ret, GetLastError());
3030 return ret;
3033 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3034 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3035 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3037 BOOL ret;
3039 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3040 pDecodePara, pvStructInfo, pcbStructInfo);
3042 __TRY
3044 DWORD bytesNeeded;
3046 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
3047 lpszStructType, pbEncoded, cbEncoded,
3048 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
3050 if (!pvStructInfo)
3051 *pcbStructInfo = bytesNeeded;
3052 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3053 pvStructInfo, pcbStructInfo, bytesNeeded)))
3055 CRYPT_BIT_BLOB *blob;
3057 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3058 pvStructInfo = *(BYTE **)pvStructInfo;
3059 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3060 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3061 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
3062 lpszStructType, pbEncoded, cbEncoded,
3063 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
3064 &bytesNeeded);
3068 __EXCEPT_PAGE_FAULT
3070 SetLastError(STATUS_ACCESS_VIOLATION);
3071 ret = FALSE;
3073 __ENDTRY
3074 TRACE("returning %d (%08x)\n", ret, GetLastError());
3075 return ret;
3078 static BOOL WINAPI CRYPT_AsnDecodeIntInternal(DWORD dwCertEncodingType,
3079 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded,
3080 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo,
3081 DWORD *pcbStructInfo)
3083 BOOL ret;
3084 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3085 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3086 DWORD size = sizeof(buf);
3088 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3089 if (pbEncoded[0] != ASN_INTEGER)
3091 SetLastError(CRYPT_E_ASN1_BADTAG);
3092 ret = FALSE;
3094 else
3095 ret = CRYPT_AsnDecodeIntegerInternal(X509_ASN_ENCODING, NULL,
3096 pbEncoded, cbEncoded, 0, NULL, &buf, &size);
3097 if (ret)
3099 if (!pvStructInfo)
3100 *pcbStructInfo = sizeof(int);
3101 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3103 int val, i;
3105 if (blob->pbData[blob->cbData - 1] & 0x80)
3107 /* initialize to a negative value to sign-extend */
3108 val = -1;
3110 else
3111 val = 0;
3112 for (i = 0; i < blob->cbData; i++)
3114 val <<= 8;
3115 val |= blob->pbData[blob->cbData - i - 1];
3117 memcpy(pvStructInfo, &val, sizeof(int));
3120 else if (GetLastError() == ERROR_MORE_DATA)
3121 SetLastError(CRYPT_E_ASN1_LARGE);
3122 return ret;
3125 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3126 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3127 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3129 BOOL ret;
3131 __TRY
3133 DWORD bytesNeeded;
3135 ret = CRYPT_AsnDecodeIntInternal(dwCertEncodingType, lpszStructType,
3136 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
3137 &bytesNeeded);
3138 if (ret)
3140 if (!pvStructInfo)
3141 *pcbStructInfo = bytesNeeded;
3142 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3143 pvStructInfo, pcbStructInfo, bytesNeeded)))
3145 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3146 pvStructInfo = *(BYTE **)pvStructInfo;
3147 ret = CRYPT_AsnDecodeIntInternal(dwCertEncodingType,
3148 lpszStructType, pbEncoded, cbEncoded,
3149 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
3150 &bytesNeeded);
3154 __EXCEPT_PAGE_FAULT
3156 SetLastError(STATUS_ACCESS_VIOLATION);
3157 ret = FALSE;
3159 __ENDTRY
3160 return ret;
3163 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
3164 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3165 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3167 BOOL ret;
3168 DWORD bytesNeeded, dataLen;
3170 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3172 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3174 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3175 if (!pvStructInfo)
3176 *pcbStructInfo = bytesNeeded;
3177 else if (*pcbStructInfo < bytesNeeded)
3179 *pcbStructInfo = bytesNeeded;
3180 SetLastError(ERROR_MORE_DATA);
3181 ret = FALSE;
3183 else
3185 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3187 blob->cbData = dataLen;
3188 assert(blob->pbData);
3189 if (blob->cbData)
3191 DWORD i;
3193 for (i = 0; i < blob->cbData; i++)
3195 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3196 dataLen - i - 1);
3201 return ret;
3204 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3205 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3206 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3208 BOOL ret;
3210 __TRY
3212 DWORD bytesNeeded;
3214 if (pbEncoded[0] != ASN_INTEGER)
3216 SetLastError(CRYPT_E_ASN1_BADTAG);
3217 ret = FALSE;
3219 else
3220 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3221 lpszStructType, pbEncoded, cbEncoded,
3222 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
3223 if (ret)
3225 if (!pvStructInfo)
3226 *pcbStructInfo = bytesNeeded;
3227 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3228 pvStructInfo, pcbStructInfo, bytesNeeded)))
3230 CRYPT_INTEGER_BLOB *blob;
3232 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3233 pvStructInfo = *(BYTE **)pvStructInfo;
3234 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3235 blob->pbData = (BYTE *)pvStructInfo +
3236 sizeof(CRYPT_INTEGER_BLOB);
3237 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3238 lpszStructType, pbEncoded, cbEncoded,
3239 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3240 &bytesNeeded);
3244 __EXCEPT_PAGE_FAULT
3246 SetLastError(STATUS_ACCESS_VIOLATION);
3247 ret = FALSE;
3249 __ENDTRY
3250 return ret;
3253 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
3254 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3255 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3256 void *pvStructInfo, DWORD *pcbStructInfo)
3258 BOOL ret;
3260 if (pbEncoded[0] == ASN_INTEGER)
3262 DWORD bytesNeeded, dataLen;
3264 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3266 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3268 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3269 if (!pvStructInfo)
3270 *pcbStructInfo = bytesNeeded;
3271 else if (*pcbStructInfo < bytesNeeded)
3273 *pcbStructInfo = bytesNeeded;
3274 SetLastError(ERROR_MORE_DATA);
3275 ret = FALSE;
3277 else
3279 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3281 blob->cbData = dataLen;
3282 assert(blob->pbData);
3283 /* remove leading zero byte if it exists */
3284 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3286 blob->cbData--;
3287 blob->pbData++;
3289 if (blob->cbData)
3291 DWORD i;
3293 for (i = 0; i < blob->cbData; i++)
3295 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3296 dataLen - i - 1);
3302 else
3304 SetLastError(CRYPT_E_ASN1_BADTAG);
3305 ret = FALSE;
3307 return ret;
3310 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3311 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3312 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3314 BOOL ret;
3316 __TRY
3318 DWORD bytesNeeded;
3320 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3321 lpszStructType, pbEncoded, cbEncoded,
3322 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
3324 if (!pvStructInfo)
3325 *pcbStructInfo = bytesNeeded;
3326 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3327 pvStructInfo, pcbStructInfo, bytesNeeded)))
3329 CRYPT_INTEGER_BLOB *blob;
3331 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3332 pvStructInfo = *(BYTE **)pvStructInfo;
3333 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3334 blob->pbData = (BYTE *)pvStructInfo +
3335 sizeof(CRYPT_INTEGER_BLOB);
3336 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3337 lpszStructType, pbEncoded, cbEncoded,
3338 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3339 &bytesNeeded);
3343 __EXCEPT_PAGE_FAULT
3345 SetLastError(STATUS_ACCESS_VIOLATION);
3346 ret = FALSE;
3348 __ENDTRY
3349 return ret;
3352 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(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(int);
3361 return TRUE;
3363 __TRY
3365 if (pbEncoded[0] == ASN_ENUMERATED)
3367 unsigned int val = 0, i;
3369 if (cbEncoded <= 1)
3371 SetLastError(CRYPT_E_ASN1_EOD);
3372 ret = FALSE;
3374 else if (pbEncoded[1] == 0)
3376 SetLastError(CRYPT_E_ASN1_CORRUPT);
3377 ret = FALSE;
3379 else
3381 /* A little strange looking, but we have to accept a sign byte:
3382 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3383 * assuming a small length is okay here, it has to be in short
3384 * form.
3386 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3388 SetLastError(CRYPT_E_ASN1_LARGE);
3389 return FALSE;
3391 for (i = 0; i < pbEncoded[1]; i++)
3393 val <<= 8;
3394 val |= pbEncoded[2 + i];
3396 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3397 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3399 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3400 pvStructInfo = *(BYTE **)pvStructInfo;
3401 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3405 else
3407 SetLastError(CRYPT_E_ASN1_BADTAG);
3408 ret = FALSE;
3411 __EXCEPT_PAGE_FAULT
3413 SetLastError(STATUS_ACCESS_VIOLATION);
3414 ret = FALSE;
3416 __ENDTRY
3417 return ret;
3420 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3421 * if it fails.
3423 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3424 do { \
3425 BYTE i; \
3427 (word) = 0; \
3428 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3430 if (!isdigit(*(pbEncoded))) \
3432 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3433 ret = FALSE; \
3435 else \
3437 (word) *= 10; \
3438 (word) += *(pbEncoded)++ - '0'; \
3441 } while (0)
3443 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3444 SYSTEMTIME *sysTime)
3446 BOOL ret;
3448 __TRY
3450 ret = TRUE;
3451 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3453 WORD hours, minutes = 0;
3454 BYTE sign = *pbEncoded++;
3456 len--;
3457 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3458 if (ret && hours >= 24)
3460 SetLastError(CRYPT_E_ASN1_CORRUPT);
3461 ret = FALSE;
3463 else if (len >= 2)
3465 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3466 if (ret && minutes >= 60)
3468 SetLastError(CRYPT_E_ASN1_CORRUPT);
3469 ret = FALSE;
3472 if (ret)
3474 if (sign == '+')
3476 sysTime->wHour += hours;
3477 sysTime->wMinute += minutes;
3479 else
3481 if (hours > sysTime->wHour)
3483 sysTime->wDay--;
3484 sysTime->wHour = 24 - (hours - sysTime->wHour);
3486 else
3487 sysTime->wHour -= hours;
3488 if (minutes > sysTime->wMinute)
3490 sysTime->wHour--;
3491 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3493 else
3494 sysTime->wMinute -= minutes;
3499 __EXCEPT_PAGE_FAULT
3501 SetLastError(STATUS_ACCESS_VIOLATION);
3502 ret = FALSE;
3504 __ENDTRY
3505 return ret;
3508 #define MIN_ENCODED_TIME_LENGTH 10
3510 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3511 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3512 DWORD *pcbDecoded)
3514 BOOL ret = FALSE;
3516 if (pbEncoded[0] == ASN_UTCTIME)
3518 if (cbEncoded <= 1)
3519 SetLastError(CRYPT_E_ASN1_EOD);
3520 else if (pbEncoded[1] > 0x7f)
3522 /* long-form date strings really can't be valid */
3523 SetLastError(CRYPT_E_ASN1_CORRUPT);
3525 else
3527 SYSTEMTIME sysTime = { 0 };
3528 BYTE len = pbEncoded[1];
3530 if (len < MIN_ENCODED_TIME_LENGTH)
3531 SetLastError(CRYPT_E_ASN1_CORRUPT);
3532 else
3534 ret = TRUE;
3535 pbEncoded += 2;
3536 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3537 if (sysTime.wYear >= 50)
3538 sysTime.wYear += 1900;
3539 else
3540 sysTime.wYear += 2000;
3541 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3542 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3543 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3544 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3545 if (ret && len > 0)
3547 if (len >= 2 && isdigit(*pbEncoded) &&
3548 isdigit(*(pbEncoded + 1)))
3549 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3550 sysTime.wSecond);
3551 else if (isdigit(*pbEncoded))
3552 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3553 sysTime.wSecond);
3554 if (ret)
3555 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3556 &sysTime);
3558 if (ret)
3560 if (!pvStructInfo)
3561 *pcbStructInfo = sizeof(FILETIME);
3562 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3563 sizeof(FILETIME))))
3564 ret = SystemTimeToFileTime(&sysTime,
3565 (FILETIME *)pvStructInfo);
3570 else
3571 SetLastError(CRYPT_E_ASN1_BADTAG);
3572 return ret;
3575 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3576 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3577 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3579 BOOL ret = FALSE;
3581 __TRY
3583 DWORD bytesNeeded;
3585 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3586 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3587 if (ret)
3589 if (!pvStructInfo)
3590 *pcbStructInfo = bytesNeeded;
3591 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3592 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3594 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3595 pvStructInfo = *(BYTE **)pvStructInfo;
3596 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3597 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3598 &bytesNeeded, NULL);
3602 __EXCEPT_PAGE_FAULT
3604 SetLastError(STATUS_ACCESS_VIOLATION);
3606 __ENDTRY
3607 return ret;
3610 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3611 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3612 DWORD *pcbDecoded)
3614 BOOL ret = FALSE;
3616 if (pbEncoded[0] == ASN_GENERALTIME)
3618 if (cbEncoded <= 1)
3619 SetLastError(CRYPT_E_ASN1_EOD);
3620 else if (pbEncoded[1] > 0x7f)
3622 /* long-form date strings really can't be valid */
3623 SetLastError(CRYPT_E_ASN1_CORRUPT);
3625 else
3627 BYTE len = pbEncoded[1];
3629 if (len < MIN_ENCODED_TIME_LENGTH)
3630 SetLastError(CRYPT_E_ASN1_CORRUPT);
3631 else
3633 SYSTEMTIME sysTime = { 0 };
3635 ret = TRUE;
3636 pbEncoded += 2;
3637 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3638 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3639 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3640 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3641 if (ret && len > 0)
3643 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3644 sysTime.wMinute);
3645 if (ret && len > 0)
3646 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3647 sysTime.wSecond);
3648 if (ret && len > 0 && (*pbEncoded == '.' ||
3649 *pbEncoded == ','))
3651 BYTE digits;
3653 pbEncoded++;
3654 len--;
3655 /* workaround macro weirdness */
3656 digits = min(len, 3);
3657 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3658 sysTime.wMilliseconds);
3660 if (ret)
3661 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3662 &sysTime);
3664 if (ret)
3666 if (!pvStructInfo)
3667 *pcbStructInfo = sizeof(FILETIME);
3668 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3669 sizeof(FILETIME))))
3670 ret = SystemTimeToFileTime(&sysTime,
3671 (FILETIME *)pvStructInfo);
3676 else
3677 SetLastError(CRYPT_E_ASN1_BADTAG);
3678 return ret;
3681 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
3682 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3683 DWORD *pcbDecoded)
3685 BOOL ret;
3686 InternalDecodeFunc decode = NULL;
3688 if (pbEncoded[0] == ASN_UTCTIME)
3689 decode = CRYPT_AsnDecodeUtcTimeInternal;
3690 else if (pbEncoded[0] == ASN_GENERALTIME)
3691 decode = CRYPT_AsnDecodeGeneralizedTime;
3692 if (decode)
3693 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
3694 pcbStructInfo, pcbDecoded);
3695 else
3697 SetLastError(CRYPT_E_ASN1_BADTAG);
3698 ret = FALSE;
3700 return ret;
3703 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3704 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3705 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3707 BOOL ret;
3709 __TRY
3711 DWORD bytesNeeded;
3713 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3714 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3715 if (ret)
3717 if (!pvStructInfo)
3718 *pcbStructInfo = bytesNeeded;
3719 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3720 pvStructInfo, pcbStructInfo, bytesNeeded)))
3722 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3723 pvStructInfo = *(BYTE **)pvStructInfo;
3724 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3725 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3726 &bytesNeeded, NULL);
3730 __EXCEPT_PAGE_FAULT
3732 SetLastError(STATUS_ACCESS_VIOLATION);
3733 ret = FALSE;
3735 __ENDTRY
3736 return ret;
3739 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3740 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3741 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3743 BOOL ret = TRUE;
3745 __TRY
3747 if (pbEncoded[0] == ASN_SEQUENCEOF)
3749 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3751 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3753 BYTE lenBytes;
3754 const BYTE *ptr;
3756 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3757 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3758 cValue = 0;
3759 ptr = pbEncoded + 1 + lenBytes;
3760 remainingLen = dataLen;
3761 while (ret && remainingLen)
3763 DWORD nextLen;
3765 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3766 if (ret)
3768 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3770 remainingLen -= 1 + nextLenBytes + nextLen;
3771 ptr += 1 + nextLenBytes + nextLen;
3772 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3773 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3774 bytesNeeded += 1 + nextLenBytes + nextLen;
3775 cValue++;
3778 if (ret)
3780 CRYPT_SEQUENCE_OF_ANY *seq;
3781 BYTE *nextPtr;
3782 DWORD i;
3784 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3785 pvStructInfo, pcbStructInfo, bytesNeeded)))
3787 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3788 pvStructInfo = *(BYTE **)pvStructInfo;
3789 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3790 seq->cValue = cValue;
3791 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3792 sizeof(*seq));
3793 nextPtr = (BYTE *)seq->rgValue +
3794 cValue * sizeof(CRYPT_DER_BLOB);
3795 ptr = pbEncoded + 1 + lenBytes;
3796 remainingLen = dataLen;
3797 i = 0;
3798 while (ret && remainingLen)
3800 DWORD nextLen;
3802 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3803 if (ret)
3805 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3807 seq->rgValue[i].cbData = 1 + nextLenBytes +
3808 nextLen;
3809 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3810 seq->rgValue[i].pbData = (BYTE *)ptr;
3811 else
3813 seq->rgValue[i].pbData = nextPtr;
3814 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3815 nextLen);
3816 nextPtr += 1 + nextLenBytes + nextLen;
3818 remainingLen -= 1 + nextLenBytes + nextLen;
3819 ptr += 1 + nextLenBytes + nextLen;
3820 i++;
3827 else
3829 SetLastError(CRYPT_E_ASN1_BADTAG);
3830 ret = FALSE;
3833 __EXCEPT_PAGE_FAULT
3835 SetLastError(STATUS_ACCESS_VIOLATION);
3836 ret = FALSE;
3838 __ENDTRY
3839 return ret;
3842 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3843 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3844 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3846 BOOL ret;
3848 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3850 DWORD bytesNeeded, dataLen;
3852 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3854 struct AsnArrayDescriptor arrayDesc = {
3855 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3856 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3857 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3858 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3860 if (dataLen)
3862 DWORD nameLen;
3864 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3865 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3866 0, NULL, NULL, &nameLen, NULL, NULL);
3867 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3869 else
3870 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3871 if (!pvStructInfo)
3872 *pcbStructInfo = bytesNeeded;
3873 else if (*pcbStructInfo < bytesNeeded)
3875 *pcbStructInfo = bytesNeeded;
3876 SetLastError(ERROR_MORE_DATA);
3877 ret = FALSE;
3879 else
3881 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3883 if (dataLen)
3885 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3886 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3887 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3888 0, NULL, &name->u.FullName, pcbStructInfo, NULL,
3889 name->u.FullName.rgAltEntry);
3891 else
3892 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3896 else
3898 SetLastError(CRYPT_E_ASN1_BADTAG);
3899 ret = FALSE;
3901 return ret;
3904 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
3905 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3907 struct AsnDecodeSequenceItem items[] = {
3908 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3909 DistPointName), CRYPT_AsnDecodeDistPointName,
3910 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3911 DistPointName.u.FullName.rgAltEntry), 0 },
3912 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3913 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3914 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3915 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3916 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3917 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3919 BOOL ret;
3921 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3922 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3923 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, NULL);
3924 return ret;
3927 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3928 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3929 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3931 BOOL ret;
3933 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3934 pDecodePara, pvStructInfo, *pcbStructInfo);
3936 __TRY
3938 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3939 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3940 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3942 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3943 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3945 __EXCEPT_PAGE_FAULT
3947 SetLastError(STATUS_ACCESS_VIOLATION);
3948 ret = FALSE;
3950 __ENDTRY
3951 return ret;
3954 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3955 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3956 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3958 BOOL ret;
3960 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3961 pDecodePara, pvStructInfo, *pcbStructInfo);
3963 __TRY
3965 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3966 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3968 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3969 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3971 __EXCEPT_PAGE_FAULT
3973 SetLastError(STATUS_ACCESS_VIOLATION);
3974 ret = FALSE;
3976 __ENDTRY
3977 return ret;
3980 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3981 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3982 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3984 BOOL ret;
3986 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3987 pDecodePara, pvStructInfo, *pcbStructInfo);
3989 __TRY
3991 struct AsnDecodeSequenceItem items[] = {
3992 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3993 DistPointName), CRYPT_AsnDecodeDistPointName,
3994 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3995 offsetof(CRL_ISSUING_DIST_POINT,
3996 DistPointName.u.FullName.rgAltEntry), 0 },
3997 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3998 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3999 FALSE, 0 },
4000 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4001 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4002 FALSE, 0 },
4003 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4004 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4005 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4006 OnlySomeReasonFlags.pbData), 0 },
4007 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4008 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4011 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
4012 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
4013 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4015 __EXCEPT_PAGE_FAULT
4017 SetLastError(STATUS_ACCESS_VIOLATION);
4018 ret = FALSE;
4020 __ENDTRY
4021 return ret;
4024 static BOOL WINAPI CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType,
4025 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4026 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4028 BOOL ret;
4029 struct AsnDecodeSequenceItem items[] = {
4030 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4031 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4032 Issuer.pbData) },
4033 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4034 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4035 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4037 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4038 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4040 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4041 pDecodePara, pvStructInfo, *pcbStructInfo);
4043 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
4044 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
4045 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL,
4046 issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4047 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4049 SetLastError(CRYPT_E_ASN1_CORRUPT);
4050 ret = FALSE;
4052 TRACE("returning %d\n", ret);
4053 return ret;
4056 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4057 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4058 DWORD *pcbDecoded)
4060 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4061 struct AsnDecodeSequenceItem items[] = {
4062 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4063 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4064 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4065 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4066 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4067 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4068 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4069 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4070 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4071 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4072 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4073 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4074 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4075 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4076 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4077 HashEncryptionAlgorithm.pszObjId), 0 },
4078 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4079 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4080 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4081 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4082 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4083 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4084 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4086 BOOL ret;
4088 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4089 pvStructInfo, *pcbStructInfo);
4091 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
4092 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
4093 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4094 info ? info->Issuer.pbData : NULL);
4095 return ret;
4098 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4099 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4100 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4102 BOOL ret = FALSE;
4104 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4105 pDecodePara, pvStructInfo, *pcbStructInfo);
4107 __TRY
4109 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4110 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4111 if (ret && pvStructInfo)
4113 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4114 pcbStructInfo, *pcbStructInfo);
4115 if (ret)
4117 CMSG_SIGNER_INFO *info;
4119 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4120 pvStructInfo = *(BYTE **)pvStructInfo;
4121 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4122 info->Issuer.pbData = ((BYTE *)info +
4123 sizeof(CMSG_SIGNER_INFO));
4124 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4125 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4126 pcbStructInfo, NULL);
4130 __EXCEPT_PAGE_FAULT
4132 SetLastError(STATUS_ACCESS_VIOLATION);
4134 __ENDTRY
4135 TRACE("returning %d\n", ret);
4136 return ret;
4139 static BOOL WINAPI CRYPT_DecodeSignerArray(DWORD dwCertEncodingType,
4140 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4141 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4143 BOOL ret;
4144 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4145 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
4146 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
4147 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4149 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4150 pDecodePara, pvStructInfo, *pcbStructInfo);
4152 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4153 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
4154 array ? array->rgItems : NULL);
4155 return ret;
4158 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4159 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4160 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4162 BOOL ret = FALSE;
4163 struct AsnDecodeSequenceItem items[] = {
4164 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4165 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4166 /* Placeholder for the hash algorithms - redundant with those in the
4167 * signers, so just ignore them.
4169 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4170 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4171 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4172 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4173 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4174 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4175 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4176 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4177 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4178 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4179 sizeof(struct GenericArray), TRUE, TRUE,
4180 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4181 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4182 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4183 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4186 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4187 pDecodePara, signedInfo, *pcbSignedInfo);
4189 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
4190 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
4191 pDecodePara, signedInfo, pcbSignedInfo, NULL, NULL);
4192 TRACE("returning %d\n", ret);
4193 return ret;
4196 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4197 LPCSTR lpszStructType)
4199 CryptDecodeObjectExFunc decodeFunc = NULL;
4201 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4202 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4204 SetLastError(ERROR_FILE_NOT_FOUND);
4205 return NULL;
4207 if (!HIWORD(lpszStructType))
4209 switch (LOWORD(lpszStructType))
4211 case (WORD)X509_CERT:
4212 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4213 break;
4214 case (WORD)X509_CERT_TO_BE_SIGNED:
4215 decodeFunc = CRYPT_AsnDecodeCert;
4216 break;
4217 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
4218 decodeFunc = CRYPT_AsnDecodeCRL;
4219 break;
4220 case (WORD)X509_EXTENSIONS:
4221 decodeFunc = CRYPT_AsnDecodeExtensions;
4222 break;
4223 case (WORD)X509_NAME_VALUE:
4224 decodeFunc = CRYPT_AsnDecodeNameValue;
4225 break;
4226 case (WORD)X509_NAME:
4227 decodeFunc = CRYPT_AsnDecodeName;
4228 break;
4229 case (WORD)X509_PUBLIC_KEY_INFO:
4230 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4231 break;
4232 case (WORD)X509_AUTHORITY_KEY_ID:
4233 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4234 break;
4235 case (WORD)X509_ALTERNATE_NAME:
4236 decodeFunc = CRYPT_AsnDecodeAltName;
4237 break;
4238 case (WORD)X509_BASIC_CONSTRAINTS:
4239 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4240 break;
4241 case (WORD)X509_BASIC_CONSTRAINTS2:
4242 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4243 break;
4244 case (WORD)RSA_CSP_PUBLICKEYBLOB:
4245 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4246 break;
4247 case (WORD)X509_UNICODE_NAME:
4248 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4249 break;
4250 case (WORD)PKCS_ATTRIBUTE:
4251 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4252 break;
4253 case (WORD)X509_UNICODE_NAME_VALUE:
4254 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4255 break;
4256 case (WORD)X509_OCTET_STRING:
4257 decodeFunc = CRYPT_AsnDecodeOctets;
4258 break;
4259 case (WORD)X509_BITS:
4260 case (WORD)X509_KEY_USAGE:
4261 decodeFunc = CRYPT_AsnDecodeBits;
4262 break;
4263 case (WORD)X509_INTEGER:
4264 decodeFunc = CRYPT_AsnDecodeInt;
4265 break;
4266 case (WORD)X509_MULTI_BYTE_INTEGER:
4267 decodeFunc = CRYPT_AsnDecodeInteger;
4268 break;
4269 case (WORD)X509_MULTI_BYTE_UINT:
4270 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4271 break;
4272 case (WORD)X509_ENUMERATED:
4273 decodeFunc = CRYPT_AsnDecodeEnumerated;
4274 break;
4275 case (WORD)X509_CHOICE_OF_TIME:
4276 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4277 break;
4278 case (WORD)X509_AUTHORITY_KEY_ID2:
4279 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4280 break;
4281 case (WORD)PKCS_CONTENT_INFO:
4282 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4283 break;
4284 case (WORD)X509_SEQUENCE_OF_ANY:
4285 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4286 break;
4287 case (WORD)PKCS_UTC_TIME:
4288 decodeFunc = CRYPT_AsnDecodeUtcTime;
4289 break;
4290 case (WORD)X509_CRL_DIST_POINTS:
4291 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4292 break;
4293 case (WORD)X509_ENHANCED_KEY_USAGE:
4294 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4295 break;
4296 case (WORD)PKCS_ATTRIBUTES:
4297 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4298 break;
4299 case (WORD)X509_ISSUING_DIST_POINT:
4300 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4301 break;
4302 case (WORD)PKCS7_SIGNER_INFO:
4303 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4304 break;
4307 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4308 decodeFunc = CRYPT_AsnDecodeExtensions;
4309 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4310 decodeFunc = CRYPT_AsnDecodeUtcTime;
4311 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4312 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4313 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4314 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4315 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4316 decodeFunc = CRYPT_AsnDecodeEnumerated;
4317 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4318 decodeFunc = CRYPT_AsnDecodeBits;
4319 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4320 decodeFunc = CRYPT_AsnDecodeOctets;
4321 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4322 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4323 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4324 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4325 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4326 decodeFunc = CRYPT_AsnDecodeAltName;
4327 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4328 decodeFunc = CRYPT_AsnDecodeAltName;
4329 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4330 decodeFunc = CRYPT_AsnDecodeAltName;
4331 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4332 decodeFunc = CRYPT_AsnDecodeAltName;
4333 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4334 decodeFunc = CRYPT_AsnDecodeAltName;
4335 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4336 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4337 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4338 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4339 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4340 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4341 return decodeFunc;
4344 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4345 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4347 static HCRYPTOIDFUNCSET set = NULL;
4348 CryptDecodeObjectFunc decodeFunc = NULL;
4350 if (!set)
4351 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4352 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4353 (void **)&decodeFunc, hFunc);
4354 return decodeFunc;
4357 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4358 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4360 static HCRYPTOIDFUNCSET set = NULL;
4361 CryptDecodeObjectExFunc decodeFunc = NULL;
4363 if (!set)
4364 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4365 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4366 (void **)&decodeFunc, hFunc);
4367 return decodeFunc;
4370 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4371 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4372 DWORD *pcbStructInfo)
4374 BOOL ret = FALSE;
4375 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4376 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4377 HCRYPTOIDFUNCADDR hFunc = NULL;
4379 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4380 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4381 pvStructInfo, pcbStructInfo);
4383 if (!pvStructInfo && !pcbStructInfo)
4385 SetLastError(ERROR_INVALID_PARAMETER);
4386 return FALSE;
4388 if (!cbEncoded)
4390 SetLastError(CRYPT_E_ASN1_EOD);
4391 return FALSE;
4393 if (cbEncoded > MAX_ENCODED_LEN)
4395 SetLastError(CRYPT_E_ASN1_LARGE);
4396 return FALSE;
4399 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4400 lpszStructType)))
4402 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4403 debugstr_a(lpszStructType));
4404 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4405 lpszStructType, &hFunc);
4406 if (!pCryptDecodeObject)
4407 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4408 lpszStructType, &hFunc);
4410 if (pCryptDecodeObject)
4411 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4412 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4413 else if (pCryptDecodeObjectEx)
4414 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4415 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4416 pvStructInfo, pcbStructInfo);
4417 if (hFunc)
4418 CryptFreeOIDFunctionAddress(hFunc, 0);
4419 TRACE_(crypt)("returning %d\n", ret);
4420 return ret;
4423 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4424 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4425 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4427 BOOL ret = FALSE;
4428 CryptDecodeObjectExFunc decodeFunc;
4429 HCRYPTOIDFUNCADDR hFunc = NULL;
4431 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4432 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4433 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4435 if (!pvStructInfo && !pcbStructInfo)
4437 SetLastError(ERROR_INVALID_PARAMETER);
4438 return FALSE;
4440 if (!cbEncoded)
4442 SetLastError(CRYPT_E_ASN1_EOD);
4443 return FALSE;
4445 if (cbEncoded > MAX_ENCODED_LEN)
4447 SetLastError(CRYPT_E_ASN1_LARGE);
4448 return FALSE;
4451 SetLastError(NOERROR);
4452 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4453 *(BYTE **)pvStructInfo = NULL;
4454 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4455 if (!decodeFunc)
4457 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4458 debugstr_a(lpszStructType));
4459 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4460 &hFunc);
4462 if (decodeFunc)
4463 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4464 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4465 else
4467 CryptDecodeObjectFunc pCryptDecodeObject =
4468 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4470 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4471 * directly, as that could cause an infinite loop.
4473 if (pCryptDecodeObject)
4475 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4477 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4478 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4479 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4480 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4481 ret = pCryptDecodeObject(dwCertEncodingType,
4482 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4483 *(BYTE **)pvStructInfo, pcbStructInfo);
4485 else
4486 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4487 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4490 if (hFunc)
4491 CryptFreeOIDFunctionAddress(hFunc, 0);
4492 TRACE_(crypt)("returning %d\n", ret);
4493 return ret;