push d2761731c253bfe9a5961252b22d8cea093833f5
[wine/hacks.git] / dlls / crypt32 / decode.c
blob1f5348c924ffdba618ea0eb79fcf145c575a9d63
1 /*
2 * Copyright 2005-2008 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 "config.h"
34 #include "wine/port.h"
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
41 #define NONAMELESSUNION
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "winnls.h"
47 #include "snmp.h"
48 #include "wine/debug.h"
49 #include "wine/exception.h"
50 #include "crypt32_private.h"
52 /* This is a bit arbitrary, but to set some limit: */
53 #define MAX_ENCODED_LEN 0x02000000
55 #define ASN_FLAGS_MASK 0xe0
56 #define ASN_TYPE_MASK 0x1f
58 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
59 WINE_DECLARE_DEBUG_CHANNEL(crypt);
61 struct GenericArray
63 DWORD cItems;
64 BYTE *rgItems;
67 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
68 DWORD, DWORD, void *, DWORD *);
69 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
70 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
72 /* Internal decoders don't do memory allocation or exception handling, and
73 * they report how many bytes they decoded.
75 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
76 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
78 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
79 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
80 DWORD *pcbDecoded);
81 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
82 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
83 DWORD *pcbDecoded);
84 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
85 * time, doesn't do memory allocation, and doesn't do exception handling.
87 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
88 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
89 DWORD *pcbDecoded);
90 /* Assumes algo->Parameters.pbData is set ahead of time. */
91 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
92 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
93 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
94 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
97 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
98 DWORD *pcbDecoded);
99 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
100 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
101 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
102 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
103 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
104 * member has been initialized, doesn't do exception handling, and doesn't do
105 * memory allocation. Also doesn't check tag, assumes the caller has checked
106 * it.
108 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
109 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
110 DWORD *pcbDecoded);
111 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
112 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
113 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
114 DWORD *pcbDecoded);
116 /* Gets the number of length bytes from the given (leading) length byte */
117 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
119 /* Helper function to get the encoded length of the data starting at pbEncoded,
120 * where pbEncoded[0] is the tag. If the data are too short to contain a
121 * length or if the length is too large for cbEncoded, sets an appropriate
122 * error code and returns FALSE. If the encoded length is unknown due to
123 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
125 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
126 DWORD *len)
128 BOOL ret;
130 if (cbEncoded <= 1)
132 SetLastError(CRYPT_E_ASN1_CORRUPT);
133 ret = FALSE;
135 else if (pbEncoded[1] <= 0x7f)
137 if (pbEncoded[1] + 1 > cbEncoded)
139 SetLastError(CRYPT_E_ASN1_EOD);
140 ret = FALSE;
142 else
144 *len = pbEncoded[1];
145 ret = TRUE;
148 else if (pbEncoded[1] == 0x80)
150 *len = CMSG_INDEFINITE_LENGTH;
151 ret = TRUE;
153 else
155 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
157 if (lenLen > sizeof(DWORD) + 1)
159 SetLastError(CRYPT_E_ASN1_LARGE);
160 ret = FALSE;
162 else if (lenLen + 2 > cbEncoded)
164 SetLastError(CRYPT_E_ASN1_CORRUPT);
165 ret = FALSE;
167 else
169 DWORD out = 0;
171 pbEncoded += 2;
172 while (--lenLen)
174 out <<= 8;
175 out |= *pbEncoded++;
177 if (out + lenLen + 1 > cbEncoded)
179 SetLastError(CRYPT_E_ASN1_EOD);
180 ret = FALSE;
182 else
184 *len = out;
185 ret = TRUE;
189 return ret;
192 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
193 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
195 BOOL ret;
197 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
198 *len == CMSG_INDEFINITE_LENGTH)
200 SetLastError(CRYPT_E_ASN1_CORRUPT);
201 ret = FALSE;
203 return ret;
206 /* Helper function to check *pcbStructInfo, set it to the required size, and
207 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
208 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
209 * pointer to the newly allocated memory.
211 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
212 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
213 DWORD bytesNeeded)
215 BOOL ret = TRUE;
217 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
219 if (pDecodePara && pDecodePara->pfnAlloc)
220 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
221 else
222 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
223 if (!*(BYTE **)pvStructInfo)
224 ret = FALSE;
225 else
226 *pcbStructInfo = bytesNeeded;
228 else if (*pcbStructInfo < bytesNeeded)
230 *pcbStructInfo = bytesNeeded;
231 SetLastError(ERROR_MORE_DATA);
232 ret = FALSE;
234 else
235 *pcbStructInfo = bytesNeeded;
236 return ret;
239 static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
241 if (pDecodePara && pDecodePara->pfnFree)
242 pDecodePara->pfnFree(pv);
243 else
244 LocalFree(pv);
247 /* Helper function to check *pcbStructInfo and set it to the required size.
248 * Assumes pvStructInfo is not NULL.
250 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
252 BOOL ret;
254 if (*pcbStructInfo < bytesNeeded)
256 *pcbStructInfo = bytesNeeded;
257 SetLastError(ERROR_MORE_DATA);
258 ret = FALSE;
260 else
262 *pcbStructInfo = bytesNeeded;
263 ret = TRUE;
265 return ret;
268 /* tag:
269 * The expected tag of the item. If tag is 0, decodeFunc is called
270 * regardless of the tag value seen.
271 * offset:
272 * A sequence is decoded into a struct. The offset member is the
273 * offset of this item within that struct.
274 * decodeFunc:
275 * The decoder function to use. If this is NULL, then the member isn't
276 * decoded, but minSize space is reserved for it.
277 * minSize:
278 * The minimum amount of space occupied after decoding. You must set this.
279 * optional:
280 * If true, and the tag doesn't match the expected tag for this item,
281 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
282 * filled with 0 for this member.
283 * hasPointer, pointerOffset:
284 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
285 * the offset within the struct of the data pointer (or to the
286 * first data pointer, if more than one exist).
287 * size:
288 * Used by CRYPT_AsnDecodeSequence, not for your use.
290 struct AsnDecodeSequenceItem
292 BYTE tag;
293 DWORD offset;
294 InternalDecodeFunc decodeFunc;
295 DWORD minSize;
296 BOOL optional;
297 BOOL hasPointer;
298 DWORD pointerOffset;
299 DWORD size;
302 /* Decodes the items in a sequence, where the items are described in items,
303 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
304 * pvStructInfo. nextData is a pointer to the memory location at which the
305 * first decoded item with a dynamic pointer should point.
306 * Upon decoding, *cbDecoded is the total number of bytes decoded.
307 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
309 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
310 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
311 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
313 BOOL ret;
314 DWORD i, decoded = 0;
315 const BYTE *ptr = pbEncoded;
317 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
318 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
320 for (i = 0, ret = TRUE; ret && i < cItem; i++)
322 if (cbEncoded - (ptr - pbEncoded) != 0)
324 DWORD itemLen;
326 if ((ret = CRYPT_GetLengthIndefinite(ptr,
327 cbEncoded - (ptr - pbEncoded), &itemLen)))
329 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
331 if (ptr[0] == items[i].tag || !items[i].tag)
333 DWORD itemEncodedLen;
335 if (itemLen == CMSG_INDEFINITE_LENGTH)
336 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
337 else
338 itemEncodedLen = 1 + itemLenBytes + itemLen;
339 if (nextData && pvStructInfo && items[i].hasPointer)
341 TRACE("Setting next pointer to %p\n",
342 nextData);
343 *(BYTE **)((BYTE *)pvStructInfo +
344 items[i].pointerOffset) = nextData;
346 if (items[i].decodeFunc)
348 DWORD itemDecoded;
350 if (pvStructInfo)
351 TRACE("decoding item %d\n", i);
352 else
353 TRACE("sizing item %d\n", i);
354 ret = items[i].decodeFunc(ptr, itemEncodedLen,
355 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
356 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
357 : NULL, &items[i].size, &itemDecoded);
358 if (ret)
360 /* Account for alignment padding */
361 if (items[i].size % sizeof(DWORD_PTR))
362 items[i].size += sizeof(DWORD_PTR) -
363 items[i].size % sizeof(DWORD_PTR);
364 TRACE("item %d size: %d\n", i, items[i].size);
365 if (nextData && items[i].hasPointer &&
366 items[i].size > items[i].minSize)
367 nextData += items[i].size - items[i].minSize;
368 if (itemDecoded > itemEncodedLen)
370 WARN("decoded length %d exceeds encoded %d\n",
371 itemDecoded, itemEncodedLen);
372 SetLastError(CRYPT_E_ASN1_CORRUPT);
373 ret = FALSE;
375 else
377 if (itemLen == CMSG_INDEFINITE_LENGTH)
379 if (itemDecoded > itemEncodedLen - 2 ||
380 *(ptr + itemDecoded) != 0 ||
381 *(ptr + itemDecoded + 1) != 0)
383 TRACE("expected 0 TLV\n");
384 SetLastError(CRYPT_E_ASN1_CORRUPT);
385 ret = FALSE;
387 else
388 itemDecoded += 2;
390 if (ret)
392 ptr += itemDecoded;
393 decoded += itemDecoded;
394 TRACE("item %d: decoded %d bytes\n", i,
395 itemDecoded);
399 else if (items[i].optional &&
400 GetLastError() == CRYPT_E_ASN1_BADTAG)
402 TRACE("skipping optional item %d\n", i);
403 items[i].size = items[i].minSize;
404 SetLastError(NOERROR);
405 ret = TRUE;
407 else
408 TRACE("item %d failed: %08x\n", i,
409 GetLastError());
411 else if (itemLen == CMSG_INDEFINITE_LENGTH)
413 ERR("can't use indefinite length encoding without a decoder\n");
414 SetLastError(CRYPT_E_ASN1_CORRUPT);
415 ret = FALSE;
417 else
419 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
420 ptr += itemEncodedLen;
421 decoded += itemEncodedLen;
422 items[i].size = items[i].minSize;
425 else if (items[i].optional)
427 TRACE("skipping optional item %d\n", i);
428 items[i].size = items[i].minSize;
430 else
432 TRACE("item %d: tag %02x doesn't match expected %02x\n",
433 i, ptr[0], items[i].tag);
434 SetLastError(CRYPT_E_ASN1_BADTAG);
435 ret = FALSE;
439 else if (items[i].optional)
441 TRACE("missing optional item %d, skipping\n", i);
442 items[i].size = items[i].minSize;
444 else
446 TRACE("not enough bytes for item %d, failing\n", i);
447 SetLastError(CRYPT_E_ASN1_CORRUPT);
448 ret = FALSE;
451 if (cbDecoded)
452 *cbDecoded = decoded;
453 TRACE("returning %d\n", ret);
454 return ret;
457 /* This decodes an arbitrary sequence into a contiguous block of memory
458 * (basically, a struct.) Each element being decoded is described by a struct
459 * AsnDecodeSequenceItem, see above.
460 * startingPointer is an optional pointer to the first place where dynamic
461 * data will be stored. If you know the starting offset, you may pass it
462 * here. Otherwise, pass NULL, and one will be inferred from the items.
464 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
465 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
466 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
467 DWORD *pcbDecoded, void *startingPointer)
469 BOOL ret;
471 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
472 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
473 startingPointer);
475 if (pbEncoded[0] == ASN_SEQUENCE)
477 DWORD dataLen;
479 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
481 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
482 const BYTE *ptr = pbEncoded + 1 + lenBytes;
483 BOOL indefinite = FALSE;
485 cbEncoded -= 1 + lenBytes;
486 if (dataLen == CMSG_INDEFINITE_LENGTH)
488 dataLen = cbEncoded;
489 indefinite = TRUE;
491 else if (cbEncoded < dataLen)
493 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
494 cbEncoded);
495 SetLastError(CRYPT_E_ASN1_CORRUPT);
496 ret = FALSE;
498 if (ret)
500 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
501 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
502 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
504 if (cbDecoded > cbEncoded - 2)
506 /* Not enough space for 0 TLV */
507 SetLastError(CRYPT_E_ASN1_CORRUPT);
508 ret = FALSE;
510 else if (*(ptr + cbDecoded) != 0 ||
511 *(ptr + cbDecoded + 1) != 0)
513 TRACE("expected 0 TLV\n");
514 SetLastError(CRYPT_E_ASN1_CORRUPT);
515 ret = FALSE;
517 else
518 cbDecoded += 2;
521 if (ret && !indefinite && cbDecoded != dataLen)
523 TRACE("expected %d decoded, got %d, failing\n", dataLen,
524 cbDecoded);
525 SetLastError(CRYPT_E_ASN1_CORRUPT);
526 ret = FALSE;
528 if (ret)
530 DWORD i, bytesNeeded = 0, structSize = 0;
532 for (i = 0; i < cItem; i++)
534 bytesNeeded += items[i].size;
535 structSize += items[i].minSize;
537 if (pcbDecoded)
538 *pcbDecoded = 1 + lenBytes + cbDecoded;
539 if (!pvStructInfo)
540 *pcbStructInfo = bytesNeeded;
541 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
542 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
544 BYTE *nextData;
546 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
547 pvStructInfo = *(BYTE **)pvStructInfo;
548 if (startingPointer)
549 nextData = (BYTE *)startingPointer;
550 else
551 nextData = (BYTE *)pvStructInfo + structSize;
552 memset(pvStructInfo, 0, structSize);
553 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
554 ptr, dataLen, dwFlags, pvStructInfo, nextData,
555 &cbDecoded);
556 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
557 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
562 else
564 SetLastError(CRYPT_E_ASN1_BADTAG);
565 ret = FALSE;
567 TRACE("returning %d (%08x)\n", ret, GetLastError());
568 return ret;
571 /* tag:
572 * The expected tag of the entire encoded array (usually a variant
573 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
574 * regardless of the tag seen.
575 * decodeFunc:
576 * used to decode each item in the array
577 * itemSize:
578 * is the minimum size of each decoded item
579 * hasPointer:
580 * indicates whether each item has a dynamic pointer
581 * pointerOffset:
582 * indicates the offset within itemSize at which the pointer exists
584 struct AsnArrayDescriptor
586 BYTE tag;
587 InternalDecodeFunc decodeFunc;
588 DWORD itemSize;
589 BOOL hasPointer;
590 DWORD pointerOffset;
593 struct AsnArrayItemSize
595 DWORD encodedLen;
596 DWORD size;
599 /* Decodes an array of like types into a struct GenericArray.
600 * The layout and decoding of the array are described by a struct
601 * AsnArrayDescriptor.
603 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
604 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
605 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
606 DWORD *pcbDecoded, void *startingPointer)
608 BOOL ret = TRUE;
610 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
611 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
612 startingPointer);
614 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
616 DWORD dataLen;
618 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
620 DWORD bytesNeeded, cItems = 0, decoded;
621 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
622 /* There can be arbitrarily many items, but there is often only one.
624 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
626 decoded = 1 + lenBytes;
627 bytesNeeded = sizeof(struct GenericArray);
628 if (dataLen)
630 const BYTE *ptr;
631 BOOL doneDecoding = FALSE;
633 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
635 if (dataLen == CMSG_INDEFINITE_LENGTH)
637 if (ptr[0] == 0)
639 doneDecoding = TRUE;
640 if (ptr[1] != 0)
642 SetLastError(CRYPT_E_ASN1_CORRUPT);
643 ret = FALSE;
645 else
646 decoded += 2;
649 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
650 doneDecoding = TRUE;
651 if (!doneDecoding)
653 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
655 /* Each item decoded may not tolerate extraneous bytes,
656 * so get the length of the next element if known.
658 if ((ret = CRYPT_GetLengthIndefinite(ptr,
659 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
661 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
662 itemEncoded = cbEncoded - (ptr - pbEncoded);
663 else
664 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
665 itemDataLen;
667 if (ret)
668 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
669 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
670 &itemDecoded);
671 if (ret)
673 cItems++;
674 if (itemSizes != &itemSize)
675 itemSizes = CryptMemRealloc(itemSizes,
676 cItems * sizeof(struct AsnArrayItemSize));
677 else if (cItems > 1)
679 itemSizes =
680 CryptMemAlloc(
681 cItems * sizeof(struct AsnArrayItemSize));
682 if (itemSizes)
683 memcpy(itemSizes, &itemSize,
684 sizeof(itemSize));
686 if (itemSizes)
688 decoded += itemDecoded;
689 itemSizes[cItems - 1].encodedLen = itemEncoded;
690 itemSizes[cItems - 1].size = size;
691 bytesNeeded += size;
692 ptr += itemEncoded;
694 else
695 ret = FALSE;
700 if (ret)
702 if (pcbDecoded)
703 *pcbDecoded = decoded;
704 if (!pvStructInfo)
705 *pcbStructInfo = bytesNeeded;
706 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
707 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
709 DWORD i;
710 BYTE *nextData;
711 const BYTE *ptr;
712 struct GenericArray *array;
714 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
715 pvStructInfo = *(BYTE **)pvStructInfo;
716 array = (struct GenericArray *)pvStructInfo;
717 array->cItems = cItems;
718 if (startingPointer)
719 array->rgItems = startingPointer;
720 else
721 array->rgItems = (BYTE *)array +
722 sizeof(struct GenericArray);
723 nextData = array->rgItems +
724 array->cItems * arrayDesc->itemSize;
725 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
726 i < cItems && ptr - pbEncoded - 1 - lenBytes <
727 dataLen; i++)
729 DWORD itemDecoded;
731 if (arrayDesc->hasPointer)
732 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
733 + arrayDesc->pointerOffset) = nextData;
734 ret = arrayDesc->decodeFunc(ptr,
735 itemSizes[i].encodedLen,
736 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
737 array->rgItems + i * arrayDesc->itemSize,
738 &itemSizes[i].size, &itemDecoded);
739 if (ret)
741 nextData += itemSizes[i].size - arrayDesc->itemSize;
742 ptr += itemDecoded;
745 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
746 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
749 if (itemSizes != &itemSize)
750 CryptMemFree(itemSizes);
753 else
755 SetLastError(CRYPT_E_ASN1_BADTAG);
756 ret = FALSE;
758 return ret;
761 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
762 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
763 * to CRYPT_E_ASN1_CORRUPT.
764 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
765 * set!
767 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
768 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
770 BOOL ret;
771 DWORD dataLen;
773 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
775 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
776 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
778 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
779 bytesNeeded += 1 + lenBytes + dataLen;
781 if (pcbDecoded)
782 *pcbDecoded = 1 + lenBytes + dataLen;
783 if (!pvStructInfo)
784 *pcbStructInfo = bytesNeeded;
785 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
787 CRYPT_DER_BLOB *blob;
789 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
790 pvStructInfo = *(BYTE **)pvStructInfo;
791 blob = (CRYPT_DER_BLOB *)pvStructInfo;
792 blob->cbData = 1 + lenBytes + dataLen;
793 if (blob->cbData)
795 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
796 blob->pbData = (BYTE *)pbEncoded;
797 else
799 assert(blob->pbData);
800 memcpy(blob->pbData, pbEncoded, blob->cbData);
803 else
805 SetLastError(CRYPT_E_ASN1_CORRUPT);
806 ret = FALSE;
810 return ret;
813 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
814 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
815 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
816 DWORD *pcbDecoded)
818 BOOL ret;
820 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
821 pvStructInfo, *pcbStructInfo, pcbDecoded);
823 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
824 * place.
826 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
827 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
828 pcbDecoded);
829 if (ret && pvStructInfo)
831 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
833 if (blob->cbData)
835 DWORD i;
836 BYTE temp;
838 for (i = 0; i < blob->cbData / 2; i++)
840 temp = blob->pbData[i];
841 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
842 blob->pbData[blob->cbData - i - 1] = temp;
846 TRACE("returning %d (%08x)\n", ret, GetLastError());
847 return ret;
850 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
851 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
852 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
854 BOOL ret = TRUE;
856 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
857 pDecodePara, pvStructInfo, *pcbStructInfo);
859 __TRY
861 struct AsnDecodeSequenceItem items[] = {
862 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
863 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
864 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
865 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
866 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
867 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
868 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
869 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
870 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
871 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
874 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
875 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
876 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
877 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
878 pcbStructInfo, NULL, NULL);
880 __EXCEPT_PAGE_FAULT
882 SetLastError(STATUS_ACCESS_VIOLATION);
883 ret = FALSE;
885 __ENDTRY
887 TRACE("Returning %d (%08x)\n", ret, GetLastError());
888 return ret;
891 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
892 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
894 BOOL ret;
895 DWORD dataLen;
897 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
899 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
901 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
902 dwFlags, pvStructInfo, pcbStructInfo, NULL);
903 if (pcbDecoded)
904 *pcbDecoded = 1 + lenBytes + dataLen;
906 return ret;
909 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
910 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
912 BOOL ret;
914 struct AsnDecodeSequenceItem items[] = {
915 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
916 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
917 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
918 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
921 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
922 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
923 pcbDecoded, NULL);
924 return ret;
927 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
928 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
929 DWORD *pcbDecoded)
931 BOOL ret;
932 DWORD dataLen;
934 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
936 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
938 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
939 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
940 if (ret && pcbDecoded)
941 *pcbDecoded = 1 + lenBytes + dataLen;
943 return ret;
946 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
947 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
948 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
950 BOOL ret = TRUE;
951 struct AsnDecodeSequenceItem items[] = {
952 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
953 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
954 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
955 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
956 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
957 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
958 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
959 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
960 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
961 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
962 Issuer.pbData) },
963 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
964 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
965 FALSE, 0 },
966 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
967 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
968 Subject.pbData) },
969 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
970 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
971 FALSE, TRUE, offsetof(CERT_INFO,
972 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
973 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
974 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
975 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
976 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
977 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
978 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
979 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
980 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
981 offsetof(CERT_INFO, rgExtension), 0 },
984 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
985 pDecodePara, pvStructInfo, *pcbStructInfo);
987 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
988 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
989 NULL, NULL);
990 if (ret && pvStructInfo)
992 CERT_INFO *info;
994 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
995 info = *(CERT_INFO **)pvStructInfo;
996 else
997 info = (CERT_INFO *)pvStructInfo;
998 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
999 !info->Subject.cbData)
1001 SetLastError(CRYPT_E_ASN1_CORRUPT);
1002 /* Don't need to deallocate, because it should have failed on the
1003 * first pass (and no memory was allocated.)
1005 ret = FALSE;
1009 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1010 return ret;
1013 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1014 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1015 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1017 BOOL ret = FALSE;
1019 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1020 pDecodePara, pvStructInfo, *pcbStructInfo);
1022 __TRY
1024 DWORD size = 0;
1026 /* Unless told not to, first try to decode it as a signed cert. */
1027 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1029 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1031 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1032 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1033 (BYTE *)&signedCert, &size);
1034 if (ret)
1036 size = 0;
1037 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1038 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1039 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1040 pvStructInfo, pcbStructInfo);
1041 LocalFree(signedCert);
1044 /* Failing that, try it as an unsigned cert */
1045 if (!ret)
1047 size = 0;
1048 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1049 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1050 pDecodePara, pvStructInfo, pcbStructInfo);
1053 __EXCEPT_PAGE_FAULT
1055 SetLastError(STATUS_ACCESS_VIOLATION);
1057 __ENDTRY
1059 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1060 return ret;
1063 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1064 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1066 BOOL ret;
1067 struct AsnDecodeSequenceItem items[] = {
1068 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1069 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1070 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1071 { 0, offsetof(CRL_ENTRY, RevocationDate),
1072 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1073 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1074 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1075 offsetof(CRL_ENTRY, rgExtension), 0 },
1077 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1079 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1080 *pcbStructInfo);
1082 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1083 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1084 entry ? entry->SerialNumber.pbData : NULL);
1085 if (ret && entry && !entry->SerialNumber.cbData)
1087 WARN("empty CRL entry serial number\n");
1088 SetLastError(CRYPT_E_ASN1_CORRUPT);
1089 ret = FALSE;
1091 return ret;
1094 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1095 * been set prior to calling.
1097 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1098 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1100 BOOL ret;
1101 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1102 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1103 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1104 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1106 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1107 pvStructInfo, *pcbStructInfo, pcbDecoded);
1109 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1110 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1111 entries ? entries->rgItems : NULL);
1112 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1113 return ret;
1116 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1117 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1118 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1120 struct AsnDecodeSequenceItem items[] = {
1121 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1122 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1123 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1124 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1125 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1126 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1127 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1128 Issuer.pbData) },
1129 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1130 sizeof(FILETIME), FALSE, FALSE, 0 },
1131 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1132 sizeof(FILETIME), TRUE, FALSE, 0 },
1133 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1134 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1135 offsetof(CRL_INFO, rgCRLEntry), 0 },
1136 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1137 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1138 offsetof(CRL_INFO, rgExtension), 0 },
1140 BOOL ret = TRUE;
1142 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1143 pDecodePara, pvStructInfo, *pcbStructInfo);
1145 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1146 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1147 NULL, NULL);
1149 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1150 return ret;
1153 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1154 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1155 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1157 BOOL ret = FALSE;
1159 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1160 pDecodePara, pvStructInfo, *pcbStructInfo);
1162 __TRY
1164 DWORD size = 0;
1166 /* Unless told not to, first try to decode it as a signed crl. */
1167 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1169 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1171 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1172 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1173 (BYTE *)&signedCrl, &size);
1174 if (ret)
1176 size = 0;
1177 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1178 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1179 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1180 pvStructInfo, pcbStructInfo);
1181 LocalFree(signedCrl);
1184 /* Failing that, try it as an unsigned crl */
1185 if (!ret)
1187 size = 0;
1188 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1189 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1190 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1193 __EXCEPT_PAGE_FAULT
1195 SetLastError(STATUS_ACCESS_VIOLATION);
1197 __ENDTRY
1199 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1200 return ret;
1203 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1204 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1206 BOOL ret = TRUE;
1207 DWORD dataLen;
1209 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1210 pvStructInfo, *pcbStructInfo);
1212 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1214 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1215 DWORD bytesNeeded = sizeof(LPSTR);
1217 if (dataLen)
1219 /* The largest possible string for the first two components
1220 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1222 char firstTwo[6];
1223 const BYTE *ptr;
1225 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1226 pbEncoded[1 + lenBytes] / 40,
1227 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1228 * 40);
1229 bytesNeeded += strlen(firstTwo) + 1;
1230 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1231 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1233 /* large enough for ".4000000" */
1234 char str[9];
1235 int val = 0;
1237 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1238 (*ptr & 0x80))
1240 val <<= 7;
1241 val |= *ptr & 0x7f;
1242 ptr++;
1244 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1245 (*ptr & 0x80))
1247 SetLastError(CRYPT_E_ASN1_CORRUPT);
1248 ret = FALSE;
1250 else
1252 val <<= 7;
1253 val |= *ptr++;
1254 snprintf(str, sizeof(str), ".%d", val);
1255 bytesNeeded += strlen(str);
1259 if (pcbDecoded)
1260 *pcbDecoded = 1 + lenBytes + dataLen;
1261 if (!pvStructInfo)
1262 *pcbStructInfo = bytesNeeded;
1263 else if (*pcbStructInfo < bytesNeeded)
1265 *pcbStructInfo = bytesNeeded;
1266 SetLastError(ERROR_MORE_DATA);
1267 ret = FALSE;
1269 else
1271 if (dataLen)
1273 const BYTE *ptr;
1274 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1276 *pszObjId = 0;
1277 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1278 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1279 40) * 40);
1280 pszObjId += strlen(pszObjId);
1281 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1282 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1284 int val = 0;
1286 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1287 (*ptr & 0x80))
1289 val <<= 7;
1290 val |= *ptr & 0x7f;
1291 ptr++;
1293 val <<= 7;
1294 val |= *ptr++;
1295 sprintf(pszObjId, ".%d", val);
1296 pszObjId += strlen(pszObjId);
1299 else
1300 *(LPSTR *)pvStructInfo = NULL;
1301 *pcbStructInfo = bytesNeeded;
1304 return ret;
1307 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1308 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1310 BOOL ret;
1312 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1313 pvStructInfo, *pcbStructInfo);
1315 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1316 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1317 pvStructInfo, pcbStructInfo, pcbDecoded);
1318 else
1320 SetLastError(CRYPT_E_ASN1_BADTAG);
1321 ret = FALSE;
1323 return ret;
1326 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1327 * ahead of time!
1329 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1330 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1332 struct AsnDecodeSequenceItem items[] = {
1333 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1334 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1335 offsetof(CERT_EXTENSION, pszObjId), 0 },
1336 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1337 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1338 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1339 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1340 offsetof(CERT_EXTENSION, Value.pbData) },
1342 BOOL ret = TRUE;
1343 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1345 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1346 *pcbStructInfo);
1348 if (ext)
1349 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1350 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1351 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1352 pcbDecoded, ext ? ext->pszObjId : NULL);
1353 if (ext)
1354 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1355 debugstr_a(ext->pszObjId));
1356 TRACE("returning %d (%08x)\n", ret, GetLastError());
1357 return ret;
1360 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1361 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1362 DWORD *pcbDecoded)
1364 BOOL ret = TRUE;
1365 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1366 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1367 offsetof(CERT_EXTENSION, pszObjId) };
1368 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1370 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1371 pvStructInfo, *pcbStructInfo, pcbDecoded);
1373 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1374 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1375 exts ? exts->rgExtension : NULL);
1376 return ret;
1379 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1380 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1381 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1383 BOOL ret = TRUE;
1385 __TRY
1387 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1388 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1389 if (ret && pvStructInfo)
1391 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1392 pcbStructInfo, *pcbStructInfo);
1393 if (ret)
1395 CERT_EXTENSIONS *exts;
1397 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1398 pvStructInfo = *(BYTE **)pvStructInfo;
1399 exts = (CERT_EXTENSIONS *)pvStructInfo;
1400 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1401 sizeof(CERT_EXTENSIONS));
1402 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1403 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1404 pcbStructInfo, NULL);
1408 __EXCEPT_PAGE_FAULT
1410 SetLastError(STATUS_ACCESS_VIOLATION);
1411 ret = FALSE;
1413 __ENDTRY
1414 return ret;
1417 /* Warning: this assumes the address of value->Value.pbData is already set, in
1418 * order to avoid overwriting memory. (In some cases, it may change it, if it
1419 * doesn't copy anything to memory.) Be sure to set it correctly!
1421 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1422 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1423 DWORD *pcbDecoded)
1425 BOOL ret = TRUE;
1426 DWORD dataLen;
1427 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1429 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1431 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1432 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1434 switch (pbEncoded[0])
1436 case ASN_OCTETSTRING:
1437 valueType = CERT_RDN_OCTET_STRING;
1438 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1439 bytesNeeded += dataLen;
1440 break;
1441 case ASN_NUMERICSTRING:
1442 valueType = CERT_RDN_NUMERIC_STRING;
1443 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1444 bytesNeeded += dataLen;
1445 break;
1446 case ASN_PRINTABLESTRING:
1447 valueType = CERT_RDN_PRINTABLE_STRING;
1448 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1449 bytesNeeded += dataLen;
1450 break;
1451 case ASN_IA5STRING:
1452 valueType = CERT_RDN_IA5_STRING;
1453 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1454 bytesNeeded += dataLen;
1455 break;
1456 case ASN_T61STRING:
1457 valueType = CERT_RDN_T61_STRING;
1458 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1459 bytesNeeded += dataLen;
1460 break;
1461 case ASN_VIDEOTEXSTRING:
1462 valueType = CERT_RDN_VIDEOTEX_STRING;
1463 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1464 bytesNeeded += dataLen;
1465 break;
1466 case ASN_GRAPHICSTRING:
1467 valueType = CERT_RDN_GRAPHIC_STRING;
1468 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1469 bytesNeeded += dataLen;
1470 break;
1471 case ASN_VISIBLESTRING:
1472 valueType = CERT_RDN_VISIBLE_STRING;
1473 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1474 bytesNeeded += dataLen;
1475 break;
1476 case ASN_GENERALSTRING:
1477 valueType = CERT_RDN_GENERAL_STRING;
1478 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1479 bytesNeeded += dataLen;
1480 break;
1481 case ASN_UNIVERSALSTRING:
1482 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1483 SetLastError(CRYPT_E_ASN1_BADTAG);
1484 return FALSE;
1485 case ASN_BMPSTRING:
1486 valueType = CERT_RDN_BMP_STRING;
1487 bytesNeeded += dataLen;
1488 break;
1489 case ASN_UTF8STRING:
1490 valueType = CERT_RDN_UTF8_STRING;
1491 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1492 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1493 break;
1494 default:
1495 SetLastError(CRYPT_E_ASN1_BADTAG);
1496 return FALSE;
1499 if (pcbDecoded)
1500 *pcbDecoded = 1 + lenBytes + dataLen;
1501 if (!value)
1502 *pcbStructInfo = bytesNeeded;
1503 else if (*pcbStructInfo < bytesNeeded)
1505 *pcbStructInfo = bytesNeeded;
1506 SetLastError(ERROR_MORE_DATA);
1507 ret = FALSE;
1509 else
1511 *pcbStructInfo = bytesNeeded;
1512 value->dwValueType = valueType;
1513 if (dataLen)
1515 DWORD i;
1517 assert(value->Value.pbData);
1518 switch (pbEncoded[0])
1520 case ASN_OCTETSTRING:
1521 case ASN_NUMERICSTRING:
1522 case ASN_PRINTABLESTRING:
1523 case ASN_IA5STRING:
1524 case ASN_T61STRING:
1525 case ASN_VIDEOTEXSTRING:
1526 case ASN_GRAPHICSTRING:
1527 case ASN_VISIBLESTRING:
1528 case ASN_GENERALSTRING:
1529 value->Value.cbData = dataLen;
1530 if (dataLen)
1532 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1533 memcpy(value->Value.pbData,
1534 pbEncoded + 1 + lenBytes, dataLen);
1535 else
1536 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1537 lenBytes;
1539 break;
1540 case ASN_BMPSTRING:
1542 LPWSTR str = (LPWSTR)value->Value.pbData;
1544 value->Value.cbData = dataLen;
1545 for (i = 0; i < dataLen / 2; i++)
1546 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1547 pbEncoded[1 + lenBytes + 2 * i + 1];
1548 break;
1550 case ASN_UTF8STRING:
1552 LPWSTR str = (LPWSTR)value->Value.pbData;
1554 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1555 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1556 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1557 break;
1561 else
1563 value->Value.cbData = 0;
1564 value->Value.pbData = NULL;
1568 return ret;
1571 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1572 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1573 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1575 BOOL ret = TRUE;
1577 __TRY
1579 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1580 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1581 if (ret && pvStructInfo)
1583 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1584 pcbStructInfo, *pcbStructInfo);
1585 if (ret)
1587 CERT_NAME_VALUE *value;
1589 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1590 pvStructInfo = *(BYTE **)pvStructInfo;
1591 value = (CERT_NAME_VALUE *)pvStructInfo;
1592 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1593 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1594 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1595 pcbStructInfo, NULL);
1599 __EXCEPT_PAGE_FAULT
1601 SetLastError(STATUS_ACCESS_VIOLATION);
1602 ret = FALSE;
1604 __ENDTRY
1605 return ret;
1608 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1609 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1610 DWORD *pcbDecoded)
1612 BOOL ret = TRUE;
1613 DWORD dataLen;
1614 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1616 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1618 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1619 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1621 switch (pbEncoded[0])
1623 case ASN_NUMERICSTRING:
1624 valueType = CERT_RDN_NUMERIC_STRING;
1625 bytesNeeded += dataLen * 2;
1626 break;
1627 case ASN_PRINTABLESTRING:
1628 valueType = CERT_RDN_PRINTABLE_STRING;
1629 bytesNeeded += dataLen * 2;
1630 break;
1631 case ASN_IA5STRING:
1632 valueType = CERT_RDN_IA5_STRING;
1633 bytesNeeded += dataLen * 2;
1634 break;
1635 case ASN_T61STRING:
1636 valueType = CERT_RDN_T61_STRING;
1637 bytesNeeded += dataLen * 2;
1638 break;
1639 case ASN_VIDEOTEXSTRING:
1640 valueType = CERT_RDN_VIDEOTEX_STRING;
1641 bytesNeeded += dataLen * 2;
1642 break;
1643 case ASN_GRAPHICSTRING:
1644 valueType = CERT_RDN_GRAPHIC_STRING;
1645 bytesNeeded += dataLen * 2;
1646 break;
1647 case ASN_VISIBLESTRING:
1648 valueType = CERT_RDN_VISIBLE_STRING;
1649 bytesNeeded += dataLen * 2;
1650 break;
1651 case ASN_GENERALSTRING:
1652 valueType = CERT_RDN_GENERAL_STRING;
1653 bytesNeeded += dataLen * 2;
1654 break;
1655 case ASN_UNIVERSALSTRING:
1656 valueType = CERT_RDN_UNIVERSAL_STRING;
1657 bytesNeeded += dataLen / 2;
1658 break;
1659 case ASN_BMPSTRING:
1660 valueType = CERT_RDN_BMP_STRING;
1661 bytesNeeded += dataLen;
1662 break;
1663 case ASN_UTF8STRING:
1664 valueType = CERT_RDN_UTF8_STRING;
1665 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1666 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1667 break;
1668 default:
1669 SetLastError(CRYPT_E_ASN1_BADTAG);
1670 return FALSE;
1673 if (pcbDecoded)
1674 *pcbDecoded = 1 + lenBytes + dataLen;
1675 if (!value)
1676 *pcbStructInfo = bytesNeeded;
1677 else if (*pcbStructInfo < bytesNeeded)
1679 *pcbStructInfo = bytesNeeded;
1680 SetLastError(ERROR_MORE_DATA);
1681 ret = FALSE;
1683 else
1685 *pcbStructInfo = bytesNeeded;
1686 value->dwValueType = valueType;
1687 if (dataLen)
1689 DWORD i;
1690 LPWSTR str = (LPWSTR)value->Value.pbData;
1692 assert(value->Value.pbData);
1693 switch (pbEncoded[0])
1695 case ASN_NUMERICSTRING:
1696 case ASN_PRINTABLESTRING:
1697 case ASN_IA5STRING:
1698 case ASN_T61STRING:
1699 case ASN_VIDEOTEXSTRING:
1700 case ASN_GRAPHICSTRING:
1701 case ASN_VISIBLESTRING:
1702 case ASN_GENERALSTRING:
1703 value->Value.cbData = dataLen * 2;
1704 for (i = 0; i < dataLen; i++)
1705 str[i] = pbEncoded[1 + lenBytes + i];
1706 break;
1707 case ASN_UNIVERSALSTRING:
1708 value->Value.cbData = dataLen / 2;
1709 for (i = 0; i < dataLen / 4; i++)
1710 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1711 | pbEncoded[1 + lenBytes + 2 * i + 3];
1712 break;
1713 case ASN_BMPSTRING:
1714 value->Value.cbData = dataLen;
1715 for (i = 0; i < dataLen / 2; i++)
1716 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1717 pbEncoded[1 + lenBytes + 2 * i + 1];
1718 break;
1719 case ASN_UTF8STRING:
1720 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1721 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1722 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1723 break;
1726 else
1728 value->Value.cbData = 0;
1729 value->Value.pbData = NULL;
1733 return ret;
1736 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1737 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1738 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1740 BOOL ret = TRUE;
1742 __TRY
1744 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1745 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1746 if (ret && pvStructInfo)
1748 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1749 pcbStructInfo, *pcbStructInfo);
1750 if (ret)
1752 CERT_NAME_VALUE *value;
1754 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1755 pvStructInfo = *(BYTE **)pvStructInfo;
1756 value = (CERT_NAME_VALUE *)pvStructInfo;
1757 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1758 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1759 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1760 pcbStructInfo, NULL);
1764 __EXCEPT_PAGE_FAULT
1766 SetLastError(STATUS_ACCESS_VIOLATION);
1767 ret = FALSE;
1769 __ENDTRY
1770 return ret;
1773 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1774 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1776 BOOL ret;
1777 struct AsnDecodeSequenceItem items[] = {
1778 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1779 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1780 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1781 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1782 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1783 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1785 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1787 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1788 pvStructInfo, *pcbStructInfo);
1790 if (attr)
1791 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1792 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1793 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1794 attr ? attr->pszObjId : NULL);
1795 if (attr)
1797 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1798 debugstr_a(attr->pszObjId));
1799 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1801 TRACE("returning %d (%08x)\n", ret, GetLastError());
1802 return ret;
1805 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1806 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1808 BOOL ret = TRUE;
1809 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1810 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1811 offsetof(CERT_RDN_ATTR, pszObjId) };
1812 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1814 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1815 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1816 rdn ? rdn->rgRDNAttr : NULL);
1817 return ret;
1820 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1821 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1822 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1824 BOOL ret = TRUE;
1826 __TRY
1828 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1829 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1830 offsetof(CERT_RDN, rgRDNAttr) };
1832 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1833 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1835 __EXCEPT_PAGE_FAULT
1837 SetLastError(STATUS_ACCESS_VIOLATION);
1838 ret = FALSE;
1840 __ENDTRY
1841 return ret;
1844 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1845 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1846 DWORD *pcbDecoded)
1848 BOOL ret;
1849 struct AsnDecodeSequenceItem items[] = {
1850 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1851 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1852 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1853 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1854 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1855 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1857 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1859 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1860 pvStructInfo, *pcbStructInfo);
1862 if (attr)
1863 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1864 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1865 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1866 attr ? attr->pszObjId : NULL);
1867 if (attr)
1869 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1870 debugstr_a(attr->pszObjId));
1871 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1873 TRACE("returning %d (%08x)\n", ret, GetLastError());
1874 return ret;
1877 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1878 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1880 BOOL ret = TRUE;
1881 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1882 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1883 offsetof(CERT_RDN_ATTR, pszObjId) };
1884 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1886 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1887 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1888 rdn ? rdn->rgRDNAttr : NULL);
1889 return ret;
1892 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1893 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1894 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1896 BOOL ret = TRUE;
1898 __TRY
1900 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1901 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1902 offsetof(CERT_RDN, rgRDNAttr) };
1904 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1905 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1907 __EXCEPT_PAGE_FAULT
1909 SetLastError(STATUS_ACCESS_VIOLATION);
1910 ret = FALSE;
1912 __ENDTRY
1913 return ret;
1916 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1917 DWORD *pcbDecoded)
1919 BOOL ret = TRUE, done = FALSE;
1920 DWORD indefiniteNestingLevels = 0, decoded = 0;
1922 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1924 do {
1925 DWORD dataLen;
1927 if (!cbEncoded)
1928 done = TRUE;
1929 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
1930 &dataLen)))
1932 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1934 if (dataLen == CMSG_INDEFINITE_LENGTH)
1936 indefiniteNestingLevels++;
1937 pbEncoded += 1 + lenBytes;
1938 cbEncoded -= 1 + lenBytes;
1939 decoded += 1 + lenBytes;
1940 TRACE("indefiniteNestingLevels = %d\n",
1941 indefiniteNestingLevels);
1943 else
1945 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
1946 indefiniteNestingLevels)
1948 indefiniteNestingLevels--;
1949 TRACE("indefiniteNestingLevels = %d\n",
1950 indefiniteNestingLevels);
1952 pbEncoded += 1 + lenBytes + dataLen;
1953 cbEncoded -= 1 + lenBytes + dataLen;
1954 decoded += 1 + lenBytes + dataLen;
1955 if (!indefiniteNestingLevels)
1956 done = TRUE;
1959 } while (ret && !done);
1960 /* If we haven't found all 0 TLVs, we haven't found the end */
1961 if (ret && indefiniteNestingLevels)
1963 SetLastError(CRYPT_E_ASN1_EOD);
1964 ret = FALSE;
1966 if (ret)
1967 *pcbDecoded = decoded;
1968 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
1969 return ret;
1972 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1973 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1974 DWORD *pcbDecoded)
1976 BOOL ret = TRUE;
1977 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
1979 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1980 pvStructInfo, *pcbStructInfo);
1982 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
1984 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1985 bytesNeeded += encodedLen;
1986 if (!pvStructInfo)
1987 *pcbStructInfo = bytesNeeded;
1988 else if (*pcbStructInfo < bytesNeeded)
1990 SetLastError(ERROR_MORE_DATA);
1991 *pcbStructInfo = bytesNeeded;
1992 ret = FALSE;
1994 else
1996 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1998 *pcbStructInfo = bytesNeeded;
1999 blob->cbData = encodedLen;
2000 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2001 blob->pbData = (LPBYTE)pbEncoded;
2002 else
2004 assert(blob->pbData);
2005 memcpy(blob->pbData, pbEncoded, blob->cbData);
2008 if (pcbDecoded)
2009 *pcbDecoded = encodedLen;
2011 return ret;
2014 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
2015 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2017 BOOL ret;
2018 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
2019 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2020 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
2022 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2023 pvStructInfo, *pcbStructInfo, pcbDecoded);
2025 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2026 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2027 array ? array->rgItems : NULL);
2028 return ret;
2031 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2032 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2033 DWORD *pcbDecoded)
2035 BOOL ret;
2036 struct AsnDecodeSequenceItem items[] = {
2037 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2038 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2039 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2040 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2041 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
2042 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2044 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2046 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2047 pvStructInfo, *pcbStructInfo);
2049 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2050 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2051 pcbDecoded, attr ? attr->pszObjId : NULL);
2052 TRACE("returning %d\n", ret);
2053 return ret;
2056 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2057 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2058 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2060 BOOL ret = FALSE;
2062 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2063 pDecodePara, pvStructInfo, *pcbStructInfo);
2065 __TRY
2067 DWORD bytesNeeded;
2069 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2070 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2071 if (ret)
2073 if (!pvStructInfo)
2074 *pcbStructInfo = bytesNeeded;
2075 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2076 pvStructInfo, pcbStructInfo, bytesNeeded)))
2078 PCRYPT_ATTRIBUTE attr;
2080 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2081 pvStructInfo = *(BYTE **)pvStructInfo;
2082 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2083 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2084 sizeof(CRYPT_ATTRIBUTE));
2085 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2086 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2087 NULL);
2091 __EXCEPT_PAGE_FAULT
2093 SetLastError(STATUS_ACCESS_VIOLATION);
2095 __ENDTRY
2096 TRACE("returning %d\n", ret);
2097 return ret;
2100 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2101 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2102 DWORD *pcbDecoded)
2104 struct AsnArrayDescriptor arrayDesc = { 0,
2105 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2106 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2107 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2108 BOOL ret;
2110 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2111 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2112 NULL);
2113 return ret;
2116 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2117 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2118 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2120 BOOL ret = FALSE;
2122 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2123 pDecodePara, pvStructInfo, *pcbStructInfo);
2125 __TRY
2127 DWORD bytesNeeded;
2129 if (!cbEncoded)
2130 SetLastError(CRYPT_E_ASN1_EOD);
2131 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2132 SetLastError(CRYPT_E_ASN1_CORRUPT);
2133 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2134 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2135 NULL)))
2137 if (!pvStructInfo)
2138 *pcbStructInfo = bytesNeeded;
2139 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2140 pvStructInfo, pcbStructInfo, bytesNeeded)))
2142 PCRYPT_ATTRIBUTES attrs;
2144 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2145 pvStructInfo = *(BYTE **)pvStructInfo;
2146 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2147 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2148 sizeof(CRYPT_ATTRIBUTES));
2149 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2150 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2151 &bytesNeeded, NULL);
2155 __EXCEPT_PAGE_FAULT
2157 SetLastError(STATUS_ACCESS_VIOLATION);
2159 __ENDTRY
2160 TRACE("returning %d\n", ret);
2161 return ret;
2164 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2165 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2167 CRYPT_ALGORITHM_IDENTIFIER *algo =
2168 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2169 BOOL ret = TRUE;
2170 struct AsnDecodeSequenceItem items[] = {
2171 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2172 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2173 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2174 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2175 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2176 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2179 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2180 pvStructInfo, *pcbStructInfo, pcbDecoded);
2182 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2183 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2184 pcbDecoded, algo ? algo->pszObjId : NULL);
2185 if (ret && pvStructInfo)
2187 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2188 debugstr_a(algo->pszObjId));
2190 return ret;
2193 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2194 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2195 DWORD *pcbDecoded)
2197 BOOL ret = TRUE;
2198 struct AsnDecodeSequenceItem items[] = {
2199 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2200 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2201 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2202 Algorithm.pszObjId) },
2203 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2204 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2205 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2207 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2209 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2210 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2211 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2212 return ret;
2215 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2216 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2217 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2219 BOOL ret = TRUE;
2221 __TRY
2223 DWORD bytesNeeded;
2225 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2226 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2228 if (!pvStructInfo)
2229 *pcbStructInfo = bytesNeeded;
2230 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2231 pvStructInfo, pcbStructInfo, bytesNeeded)))
2233 PCERT_PUBLIC_KEY_INFO info;
2235 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2236 pvStructInfo = *(BYTE **)pvStructInfo;
2237 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2238 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2239 sizeof(CERT_PUBLIC_KEY_INFO);
2240 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2241 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2242 &bytesNeeded, NULL);
2246 __EXCEPT_PAGE_FAULT
2248 SetLastError(STATUS_ACCESS_VIOLATION);
2249 ret = FALSE;
2251 __ENDTRY
2252 return ret;
2255 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2256 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2258 BOOL ret;
2260 if (cbEncoded < 3)
2262 SetLastError(CRYPT_E_ASN1_CORRUPT);
2263 return FALSE;
2265 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2267 SetLastError(CRYPT_E_ASN1_CORRUPT);
2268 return FALSE;
2270 if (pbEncoded[1] > 1)
2272 SetLastError(CRYPT_E_ASN1_CORRUPT);
2273 return FALSE;
2275 if (pcbDecoded)
2276 *pcbDecoded = 3;
2277 if (!pvStructInfo)
2279 *pcbStructInfo = sizeof(BOOL);
2280 ret = TRUE;
2282 else if (*pcbStructInfo < sizeof(BOOL))
2284 *pcbStructInfo = sizeof(BOOL);
2285 SetLastError(ERROR_MORE_DATA);
2286 ret = FALSE;
2288 else
2290 *pcbStructInfo = sizeof(BOOL);
2291 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2292 ret = TRUE;
2294 TRACE("returning %d (%08x)\n", ret, GetLastError());
2295 return ret;
2298 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2299 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2301 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2302 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2303 BOOL ret;
2305 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2306 pvStructInfo, *pcbStructInfo);
2308 if (cbEncoded < 2)
2310 SetLastError(CRYPT_E_ASN1_CORRUPT);
2311 return FALSE;
2313 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2314 if (1 + lenBytes > cbEncoded)
2316 SetLastError(CRYPT_E_ASN1_CORRUPT);
2317 return FALSE;
2319 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2321 switch (pbEncoded[0] & ASN_TYPE_MASK)
2323 case 1: /* rfc822Name */
2324 case 2: /* dNSName */
2325 case 6: /* uniformResourceIdentifier */
2326 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2327 break;
2328 case 4: /* directoryName */
2329 case 7: /* iPAddress */
2330 bytesNeeded += dataLen;
2331 break;
2332 case 8: /* registeredID */
2333 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2334 &dataLen, NULL);
2335 if (ret)
2337 /* FIXME: ugly, shouldn't need to know internals of OID decode
2338 * function to use it.
2340 bytesNeeded += dataLen - sizeof(LPSTR);
2342 break;
2343 case 0: /* otherName */
2344 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2345 SetLastError(CRYPT_E_ASN1_BADTAG);
2346 ret = FALSE;
2347 break;
2348 case 3: /* x400Address, unimplemented */
2349 case 5: /* ediPartyName, unimplemented */
2350 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2351 SetLastError(CRYPT_E_ASN1_BADTAG);
2352 ret = FALSE;
2353 break;
2354 default:
2355 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2356 SetLastError(CRYPT_E_ASN1_CORRUPT);
2357 ret = FALSE;
2359 if (ret)
2361 if (pcbDecoded)
2362 *pcbDecoded = 1 + lenBytes + dataLen;
2363 if (!entry)
2364 *pcbStructInfo = bytesNeeded;
2365 else if (*pcbStructInfo < bytesNeeded)
2367 *pcbStructInfo = bytesNeeded;
2368 SetLastError(ERROR_MORE_DATA);
2369 ret = FALSE;
2371 else
2373 *pcbStructInfo = bytesNeeded;
2374 /* MS used values one greater than the asn1 ones.. sigh */
2375 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2376 switch (pbEncoded[0] & ASN_TYPE_MASK)
2378 case 1: /* rfc822Name */
2379 case 2: /* dNSName */
2380 case 6: /* uniformResourceIdentifier */
2382 DWORD i;
2384 for (i = 0; i < dataLen; i++)
2385 entry->u.pwszURL[i] =
2386 (WCHAR)pbEncoded[1 + lenBytes + i];
2387 entry->u.pwszURL[i] = 0;
2388 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2389 debugstr_w(entry->u.pwszURL));
2390 break;
2392 case 4: /* directoryName */
2393 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2394 /* The data are memory-equivalent with the IPAddress case,
2395 * fall-through
2397 case 7: /* iPAddress */
2398 /* The next data pointer is in the pwszURL spot, that is,
2399 * the first 4 bytes. Need to move it to the next spot.
2401 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2402 entry->u.IPAddress.cbData = dataLen;
2403 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2404 dataLen);
2405 break;
2406 case 8: /* registeredID */
2407 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2408 &entry->u.pszRegisteredID, &dataLen, NULL);
2409 break;
2414 return ret;
2417 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2418 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2419 DWORD *pcbDecoded)
2421 BOOL ret = TRUE;
2422 struct AsnArrayDescriptor arrayDesc = { 0,
2423 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2424 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2425 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2427 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2428 pvStructInfo, *pcbStructInfo, pcbDecoded);
2430 if (info)
2431 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2432 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2433 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2434 info ? info->rgAltEntry : NULL);
2435 return ret;
2438 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2439 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2440 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2441 DWORD *pcbDecoded)
2443 BOOL ret;
2445 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2446 pvStructInfo, *pcbStructInfo, pcbDecoded);
2448 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2449 * place.
2451 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2452 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2453 pcbDecoded);
2454 if (ret && pvStructInfo)
2456 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2458 if (blob->cbData)
2460 DWORD i;
2461 BYTE temp;
2463 for (i = 0; i < blob->cbData / 2; i++)
2465 temp = blob->pbData[i];
2466 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2467 blob->pbData[blob->cbData - i - 1] = temp;
2471 TRACE("returning %d (%08x)\n", ret, GetLastError());
2472 return ret;
2475 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2476 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2477 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2479 BOOL ret;
2481 __TRY
2483 struct AsnDecodeSequenceItem items[] = {
2484 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2485 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2486 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2487 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2488 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2489 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2490 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2491 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2492 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2493 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2494 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2497 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2498 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2499 pcbStructInfo, NULL, NULL);
2501 __EXCEPT_PAGE_FAULT
2503 SetLastError(STATUS_ACCESS_VIOLATION);
2504 ret = FALSE;
2506 __ENDTRY
2507 return ret;
2510 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2511 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2512 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2514 BOOL ret;
2516 __TRY
2518 struct AsnDecodeSequenceItem items[] = {
2519 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2520 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2521 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2522 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2523 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2524 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2525 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2526 AuthorityCertIssuer.rgAltEntry), 0 },
2527 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2528 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2529 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2530 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2531 AuthorityCertSerialNumber.pbData), 0 },
2534 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2535 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2536 pcbStructInfo, NULL, NULL);
2538 __EXCEPT_PAGE_FAULT
2540 SetLastError(STATUS_ACCESS_VIOLATION);
2541 ret = FALSE;
2543 __ENDTRY
2544 return ret;
2547 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
2548 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2550 BOOL ret;
2551 DWORD dataLen;
2553 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2554 pvStructInfo, *pcbStructInfo, pcbDecoded);
2556 /* The caller has already checked the tag, no need to check it again.
2557 * Check the outer length is valid:
2559 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
2561 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2562 DWORD innerLen;
2564 pbEncoded += 1 + lenBytes;
2565 cbEncoded -= 1 + lenBytes;
2566 if (dataLen == CMSG_INDEFINITE_LENGTH)
2567 cbEncoded -= 2; /* space for 0 TLV */
2568 /* Check the inner length is valid: */
2569 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
2571 DWORD decodedLen;
2573 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
2574 pvStructInfo, pcbStructInfo, &decodedLen);
2575 if (dataLen == CMSG_INDEFINITE_LENGTH)
2577 if (*(pbEncoded + decodedLen) != 0 ||
2578 *(pbEncoded + decodedLen + 1) != 0)
2580 TRACE("expected 0 TLV, got {%02x,%02x}\n",
2581 *(pbEncoded + decodedLen),
2582 *(pbEncoded + decodedLen + 1));
2583 SetLastError(CRYPT_E_ASN1_CORRUPT);
2584 ret = FALSE;
2586 else
2587 decodedLen += 2;
2589 if (ret && pcbDecoded)
2591 *pcbDecoded = 1 + lenBytes + decodedLen;
2592 TRACE("decoded %d bytes\n", *pcbDecoded);
2596 return ret;
2599 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
2600 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2601 DWORD *pcbDecoded)
2603 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2604 struct AsnDecodeSequenceItem items[] = {
2605 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2606 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2607 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2608 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2609 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2610 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2611 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2613 BOOL ret;
2615 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2616 pvStructInfo, *pcbStructInfo, pcbDecoded);
2618 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2619 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2620 pcbDecoded, info ? info->pszObjId : NULL);
2621 return ret;
2624 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2625 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2626 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2628 BOOL ret = FALSE;
2630 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2631 pDecodePara, pvStructInfo, *pcbStructInfo);
2633 __TRY
2635 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
2636 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2637 if (ret && pvStructInfo)
2639 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2640 pcbStructInfo, *pcbStructInfo);
2641 if (ret)
2643 CRYPT_CONTENT_INFO *info;
2645 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2646 pvStructInfo = *(BYTE **)pvStructInfo;
2647 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2648 info->pszObjId = (LPSTR)((BYTE *)info +
2649 sizeof(CRYPT_CONTENT_INFO));
2650 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
2651 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2652 pcbStructInfo, NULL);
2656 __EXCEPT_PAGE_FAULT
2658 SetLastError(STATUS_ACCESS_VIOLATION);
2660 __ENDTRY
2661 return ret;
2664 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2665 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2666 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2668 BOOL ret;
2669 struct AsnDecodeSequenceItem items[] = {
2670 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2671 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2672 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2673 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2674 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2675 0 },
2676 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2677 CRYPT_AsnDecodePKCSContentInfoInternal,
2678 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2679 ContentInfo.pszObjId), 0 },
2680 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2681 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2682 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2685 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2686 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
2687 NULL, NULL);
2688 return ret;
2691 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2692 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2693 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2695 BOOL ret = TRUE;
2697 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2698 pDecodePara, pvStructInfo, *pcbStructInfo);
2700 __TRY
2702 DWORD bytesNeeded;
2704 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2705 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2707 if (!pvStructInfo)
2708 *pcbStructInfo = bytesNeeded;
2709 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2710 pvStructInfo, pcbStructInfo, bytesNeeded)))
2712 CERT_ALT_NAME_INFO *name;
2714 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2715 pvStructInfo = *(BYTE **)pvStructInfo;
2716 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2717 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2718 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2719 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2720 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2721 &bytesNeeded, NULL);
2725 __EXCEPT_PAGE_FAULT
2727 SetLastError(STATUS_ACCESS_VIOLATION);
2728 ret = FALSE;
2730 __ENDTRY
2731 return ret;
2734 struct PATH_LEN_CONSTRAINT
2736 BOOL fPathLenConstraint;
2737 DWORD dwPathLenConstraint;
2740 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
2741 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2742 DWORD *pcbDecoded)
2744 BOOL ret = TRUE;
2745 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
2747 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2748 pvStructInfo, *pcbStructInfo, pcbDecoded);
2750 if (!pvStructInfo)
2752 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
2753 &size, pcbDecoded);
2754 *pcbStructInfo = bytesNeeded;
2756 else if (*pcbStructInfo < bytesNeeded)
2758 SetLastError(ERROR_MORE_DATA);
2759 *pcbStructInfo = bytesNeeded;
2760 ret = FALSE;
2762 else
2764 struct PATH_LEN_CONSTRAINT *constraint =
2765 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2767 *pcbStructInfo = bytesNeeded;
2768 size = sizeof(constraint->dwPathLenConstraint);
2769 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
2770 &constraint->dwPathLenConstraint, &size, pcbDecoded);
2771 if (ret)
2772 constraint->fPathLenConstraint = TRUE;
2773 TRACE("got an int, dwPathLenConstraint is %d\n",
2774 constraint->dwPathLenConstraint);
2776 TRACE("returning %d (%08x)\n", ret, GetLastError());
2777 return ret;
2780 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
2781 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2782 DWORD *pcbDecoded)
2784 BOOL ret;
2785 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2786 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2787 offsetof(CERT_NAME_BLOB, pbData) };
2788 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2790 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2791 pvStructInfo, *pcbStructInfo, pcbDecoded);
2793 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2794 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2795 entries ? entries->rgItems : NULL);
2796 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2797 return ret;
2800 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2801 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2802 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2804 BOOL ret;
2806 __TRY
2808 struct AsnDecodeSequenceItem items[] = {
2809 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2810 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2811 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2812 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2813 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2814 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2815 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2816 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2817 sizeof(struct GenericArray), TRUE, TRUE,
2818 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2821 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2822 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2823 pcbStructInfo, NULL, NULL);
2825 __EXCEPT_PAGE_FAULT
2827 SetLastError(STATUS_ACCESS_VIOLATION);
2828 ret = FALSE;
2830 __ENDTRY
2831 return ret;
2834 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2835 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2836 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2838 BOOL ret;
2840 __TRY
2842 struct AsnDecodeSequenceItem items[] = {
2843 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2844 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2845 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2846 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2847 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2850 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2851 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2852 pcbStructInfo, NULL, NULL);
2854 __EXCEPT_PAGE_FAULT
2856 SetLastError(STATUS_ACCESS_VIOLATION);
2857 ret = FALSE;
2859 __ENDTRY
2860 return ret;
2863 #define RSA1_MAGIC 0x31415352
2865 struct DECODED_RSA_PUB_KEY
2867 DWORD pubexp;
2868 CRYPT_INTEGER_BLOB modulus;
2871 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2872 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2873 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2875 BOOL ret;
2877 __TRY
2879 struct AsnDecodeSequenceItem items[] = {
2880 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2881 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2882 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2883 0 },
2884 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2885 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2887 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2888 DWORD size = 0;
2890 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2891 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
2892 &size, NULL, NULL);
2893 if (ret)
2895 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2896 decodedKey->modulus.cbData;
2898 if (!pvStructInfo)
2900 *pcbStructInfo = bytesNeeded;
2901 ret = TRUE;
2903 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2904 pvStructInfo, pcbStructInfo, bytesNeeded)))
2906 BLOBHEADER *hdr;
2907 RSAPUBKEY *rsaPubKey;
2909 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2910 pvStructInfo = *(BYTE **)pvStructInfo;
2911 hdr = (BLOBHEADER *)pvStructInfo;
2912 hdr->bType = PUBLICKEYBLOB;
2913 hdr->bVersion = CUR_BLOB_VERSION;
2914 hdr->reserved = 0;
2915 hdr->aiKeyAlg = CALG_RSA_KEYX;
2916 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2917 sizeof(BLOBHEADER));
2918 rsaPubKey->magic = RSA1_MAGIC;
2919 rsaPubKey->pubexp = decodedKey->pubexp;
2920 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2921 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2922 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2923 decodedKey->modulus.cbData);
2925 LocalFree(decodedKey);
2928 __EXCEPT_PAGE_FAULT
2930 SetLastError(STATUS_ACCESS_VIOLATION);
2931 ret = FALSE;
2933 __ENDTRY
2934 return ret;
2937 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
2938 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2939 DWORD *pcbDecoded)
2941 BOOL ret;
2942 DWORD bytesNeeded, dataLen;
2944 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2945 pvStructInfo, *pcbStructInfo, pcbDecoded);
2947 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2949 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2951 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2952 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2953 else
2954 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2955 if (pcbDecoded)
2956 *pcbDecoded = 1 + lenBytes + dataLen;
2957 if (!pvStructInfo)
2958 *pcbStructInfo = bytesNeeded;
2959 else if (*pcbStructInfo < bytesNeeded)
2961 SetLastError(ERROR_MORE_DATA);
2962 *pcbStructInfo = bytesNeeded;
2963 ret = FALSE;
2965 else
2967 CRYPT_DATA_BLOB *blob;
2969 *pcbStructInfo = bytesNeeded;
2970 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2971 blob->cbData = dataLen;
2972 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2973 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2974 else
2976 assert(blob->pbData);
2977 if (blob->cbData)
2978 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2979 blob->cbData);
2983 return ret;
2986 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2987 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2988 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2990 BOOL ret;
2992 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2993 pDecodePara, pvStructInfo, *pcbStructInfo);
2995 __TRY
2997 DWORD bytesNeeded;
2999 if (!cbEncoded)
3001 SetLastError(CRYPT_E_ASN1_CORRUPT);
3002 ret = FALSE;
3004 else if (pbEncoded[0] != ASN_OCTETSTRING)
3006 SetLastError(CRYPT_E_ASN1_BADTAG);
3007 ret = FALSE;
3009 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3010 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3012 if (!pvStructInfo)
3013 *pcbStructInfo = bytesNeeded;
3014 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3015 pvStructInfo, pcbStructInfo, bytesNeeded)))
3017 CRYPT_DATA_BLOB *blob;
3019 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3020 pvStructInfo = *(BYTE **)pvStructInfo;
3021 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3022 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
3023 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3024 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3025 &bytesNeeded, NULL);
3029 __EXCEPT_PAGE_FAULT
3031 SetLastError(STATUS_ACCESS_VIOLATION);
3032 ret = FALSE;
3034 __ENDTRY
3035 return ret;
3038 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3039 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3041 BOOL ret;
3043 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3044 pvStructInfo, *pcbStructInfo, pcbDecoded);
3046 if (pbEncoded[0] == ASN_BITSTRING)
3048 DWORD bytesNeeded, dataLen;
3049 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3051 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3053 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3054 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3055 else
3056 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3057 if (pcbDecoded)
3058 *pcbDecoded = 1 + lenBytes + dataLen;
3059 if (!pvStructInfo)
3060 *pcbStructInfo = bytesNeeded;
3061 else if (*pcbStructInfo < bytesNeeded)
3063 *pcbStructInfo = bytesNeeded;
3064 SetLastError(ERROR_MORE_DATA);
3065 ret = FALSE;
3067 else
3069 CRYPT_BIT_BLOB *blob;
3071 *pcbStructInfo = bytesNeeded;
3072 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3073 blob->cbData = dataLen - 1;
3074 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3075 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3077 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3079 else
3081 assert(blob->pbData);
3082 if (blob->cbData)
3084 BYTE mask = 0xff << blob->cUnusedBits;
3086 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3087 blob->cbData);
3088 blob->pbData[blob->cbData - 1] &= mask;
3094 else
3096 SetLastError(CRYPT_E_ASN1_BADTAG);
3097 ret = FALSE;
3099 TRACE("returning %d (%08x)\n", ret, GetLastError());
3100 return ret;
3103 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3104 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3105 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3107 BOOL ret;
3109 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3110 pDecodePara, pvStructInfo, pcbStructInfo);
3112 __TRY
3114 DWORD bytesNeeded;
3116 if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3117 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3119 if (!pvStructInfo)
3120 *pcbStructInfo = bytesNeeded;
3121 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3122 pvStructInfo, pcbStructInfo, bytesNeeded)))
3124 CRYPT_BIT_BLOB *blob;
3126 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3127 pvStructInfo = *(BYTE **)pvStructInfo;
3128 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3129 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3130 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3131 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3132 &bytesNeeded, NULL);
3136 __EXCEPT_PAGE_FAULT
3138 SetLastError(STATUS_ACCESS_VIOLATION);
3139 ret = FALSE;
3141 __ENDTRY
3142 TRACE("returning %d (%08x)\n", ret, GetLastError());
3143 return ret;
3146 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
3147 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3148 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3150 BOOL ret;
3151 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3152 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3153 DWORD size = sizeof(buf);
3155 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3156 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, buf,
3157 &size, pcbDecoded);
3158 if (ret)
3160 if (!pvStructInfo)
3161 *pcbStructInfo = sizeof(int);
3162 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3164 int val, i;
3166 if (blob->pbData[blob->cbData - 1] & 0x80)
3168 /* initialize to a negative value to sign-extend */
3169 val = -1;
3171 else
3172 val = 0;
3173 for (i = 0; i < blob->cbData; i++)
3175 val <<= 8;
3176 val |= blob->pbData[blob->cbData - i - 1];
3178 memcpy(pvStructInfo, &val, sizeof(int));
3181 else if (GetLastError() == ERROR_MORE_DATA)
3182 SetLastError(CRYPT_E_ASN1_LARGE);
3183 return ret;
3186 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3187 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3188 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3190 BOOL ret;
3192 __TRY
3194 DWORD bytesNeeded;
3196 if (!cbEncoded)
3198 SetLastError(CRYPT_E_ASN1_CORRUPT);
3199 ret = FALSE;
3201 else if (pbEncoded[0] != ASN_INTEGER)
3203 SetLastError(CRYPT_E_ASN1_BADTAG);
3204 ret = FALSE;
3206 else
3207 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3208 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3209 if (ret)
3211 if (!pvStructInfo)
3212 *pcbStructInfo = bytesNeeded;
3213 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3214 pvStructInfo, pcbStructInfo, bytesNeeded)))
3216 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3217 pvStructInfo = *(BYTE **)pvStructInfo;
3218 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3219 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3220 &bytesNeeded, NULL);
3224 __EXCEPT_PAGE_FAULT
3226 SetLastError(STATUS_ACCESS_VIOLATION);
3227 ret = FALSE;
3229 __ENDTRY
3230 return ret;
3233 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3234 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3235 DWORD *pcbDecoded)
3237 BOOL ret;
3238 DWORD bytesNeeded, dataLen;
3240 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3242 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3244 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3245 if (pcbDecoded)
3246 *pcbDecoded = 1 + lenBytes + dataLen;
3247 if (!pvStructInfo)
3248 *pcbStructInfo = bytesNeeded;
3249 else if (*pcbStructInfo < bytesNeeded)
3251 *pcbStructInfo = bytesNeeded;
3252 SetLastError(ERROR_MORE_DATA);
3253 ret = FALSE;
3255 else
3257 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3259 *pcbStructInfo = bytesNeeded;
3260 blob->cbData = dataLen;
3261 assert(blob->pbData);
3262 if (blob->cbData)
3264 DWORD i;
3266 for (i = 0; i < blob->cbData; i++)
3268 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3269 dataLen - i - 1);
3274 return ret;
3277 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3278 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3279 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3281 BOOL ret;
3283 __TRY
3285 DWORD bytesNeeded;
3287 if (pbEncoded[0] != ASN_INTEGER)
3289 SetLastError(CRYPT_E_ASN1_BADTAG);
3290 ret = FALSE;
3292 else
3293 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3294 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3295 if (ret)
3297 if (!pvStructInfo)
3298 *pcbStructInfo = bytesNeeded;
3299 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3300 pvStructInfo, pcbStructInfo, bytesNeeded)))
3302 CRYPT_INTEGER_BLOB *blob;
3304 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3305 pvStructInfo = *(BYTE **)pvStructInfo;
3306 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3307 blob->pbData = (BYTE *)pvStructInfo +
3308 sizeof(CRYPT_INTEGER_BLOB);
3309 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3310 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3311 &bytesNeeded, NULL);
3315 __EXCEPT_PAGE_FAULT
3317 SetLastError(STATUS_ACCESS_VIOLATION);
3318 ret = FALSE;
3320 __ENDTRY
3321 return ret;
3324 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3325 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3326 DWORD *pcbDecoded)
3328 BOOL ret;
3330 if (pbEncoded[0] == ASN_INTEGER)
3332 DWORD bytesNeeded, dataLen;
3334 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3336 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3338 if (pcbDecoded)
3339 *pcbDecoded = 1 + lenBytes + dataLen;
3340 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3341 if (!pvStructInfo)
3342 *pcbStructInfo = bytesNeeded;
3343 else if (*pcbStructInfo < bytesNeeded)
3345 *pcbStructInfo = bytesNeeded;
3346 SetLastError(ERROR_MORE_DATA);
3347 ret = FALSE;
3349 else
3351 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3353 *pcbStructInfo = bytesNeeded;
3354 blob->cbData = dataLen;
3355 assert(blob->pbData);
3356 /* remove leading zero byte if it exists */
3357 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3359 blob->cbData--;
3360 blob->pbData++;
3362 if (blob->cbData)
3364 DWORD i;
3366 for (i = 0; i < blob->cbData; i++)
3368 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3369 dataLen - i - 1);
3375 else
3377 SetLastError(CRYPT_E_ASN1_BADTAG);
3378 ret = FALSE;
3380 return ret;
3383 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3384 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3385 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3387 BOOL ret;
3389 __TRY
3391 DWORD bytesNeeded;
3393 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
3394 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3396 if (!pvStructInfo)
3397 *pcbStructInfo = bytesNeeded;
3398 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3399 pvStructInfo, pcbStructInfo, bytesNeeded)))
3401 CRYPT_INTEGER_BLOB *blob;
3403 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3404 pvStructInfo = *(BYTE **)pvStructInfo;
3405 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3406 blob->pbData = (BYTE *)pvStructInfo +
3407 sizeof(CRYPT_INTEGER_BLOB);
3408 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
3409 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3410 &bytesNeeded, NULL);
3414 __EXCEPT_PAGE_FAULT
3416 SetLastError(STATUS_ACCESS_VIOLATION);
3417 ret = FALSE;
3419 __ENDTRY
3420 return ret;
3423 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3424 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3425 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3427 BOOL ret;
3429 if (!pvStructInfo)
3431 *pcbStructInfo = sizeof(int);
3432 return TRUE;
3434 __TRY
3436 if (pbEncoded[0] == ASN_ENUMERATED)
3438 unsigned int val = 0, i;
3440 if (cbEncoded <= 1)
3442 SetLastError(CRYPT_E_ASN1_EOD);
3443 ret = FALSE;
3445 else if (pbEncoded[1] == 0)
3447 SetLastError(CRYPT_E_ASN1_CORRUPT);
3448 ret = FALSE;
3450 else
3452 /* A little strange looking, but we have to accept a sign byte:
3453 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3454 * assuming a small length is okay here, it has to be in short
3455 * form.
3457 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3459 SetLastError(CRYPT_E_ASN1_LARGE);
3460 return FALSE;
3462 for (i = 0; i < pbEncoded[1]; i++)
3464 val <<= 8;
3465 val |= pbEncoded[2 + i];
3467 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3468 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3470 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3471 pvStructInfo = *(BYTE **)pvStructInfo;
3472 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3476 else
3478 SetLastError(CRYPT_E_ASN1_BADTAG);
3479 ret = FALSE;
3482 __EXCEPT_PAGE_FAULT
3484 SetLastError(STATUS_ACCESS_VIOLATION);
3485 ret = FALSE;
3487 __ENDTRY
3488 return ret;
3491 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3492 * if it fails.
3494 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3495 do { \
3496 BYTE i; \
3498 (word) = 0; \
3499 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3501 if (!isdigit(*(pbEncoded))) \
3503 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3504 ret = FALSE; \
3506 else \
3508 (word) *= 10; \
3509 (word) += *(pbEncoded)++ - '0'; \
3512 } while (0)
3514 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3515 SYSTEMTIME *sysTime)
3517 BOOL ret = TRUE;
3519 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3521 WORD hours, minutes = 0;
3522 BYTE sign = *pbEncoded++;
3524 len--;
3525 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3526 if (ret && hours >= 24)
3528 SetLastError(CRYPT_E_ASN1_CORRUPT);
3529 ret = FALSE;
3531 else if (len >= 2)
3533 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3534 if (ret && minutes >= 60)
3536 SetLastError(CRYPT_E_ASN1_CORRUPT);
3537 ret = FALSE;
3540 if (ret)
3542 if (sign == '+')
3544 sysTime->wHour += hours;
3545 sysTime->wMinute += minutes;
3547 else
3549 if (hours > sysTime->wHour)
3551 sysTime->wDay--;
3552 sysTime->wHour = 24 - (hours - sysTime->wHour);
3554 else
3555 sysTime->wHour -= hours;
3556 if (minutes > sysTime->wMinute)
3558 sysTime->wHour--;
3559 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3561 else
3562 sysTime->wMinute -= minutes;
3566 return ret;
3569 #define MIN_ENCODED_TIME_LENGTH 10
3571 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3572 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3573 DWORD *pcbDecoded)
3575 BOOL ret = FALSE;
3577 if (pbEncoded[0] == ASN_UTCTIME)
3579 if (cbEncoded <= 1)
3580 SetLastError(CRYPT_E_ASN1_EOD);
3581 else if (pbEncoded[1] > 0x7f)
3583 /* long-form date strings really can't be valid */
3584 SetLastError(CRYPT_E_ASN1_CORRUPT);
3586 else
3588 SYSTEMTIME sysTime = { 0 };
3589 BYTE len = pbEncoded[1];
3591 if (len < MIN_ENCODED_TIME_LENGTH)
3592 SetLastError(CRYPT_E_ASN1_CORRUPT);
3593 else
3595 ret = TRUE;
3596 if (pcbDecoded)
3597 *pcbDecoded = 2 + len;
3598 pbEncoded += 2;
3599 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3600 if (sysTime.wYear >= 50)
3601 sysTime.wYear += 1900;
3602 else
3603 sysTime.wYear += 2000;
3604 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3605 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3606 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3607 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3608 if (ret && len > 0)
3610 if (len >= 2 && isdigit(*pbEncoded) &&
3611 isdigit(*(pbEncoded + 1)))
3612 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3613 sysTime.wSecond);
3614 else if (isdigit(*pbEncoded))
3615 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3616 sysTime.wSecond);
3617 if (ret)
3618 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3619 &sysTime);
3621 if (ret)
3623 if (!pvStructInfo)
3624 *pcbStructInfo = sizeof(FILETIME);
3625 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3626 sizeof(FILETIME))))
3627 ret = SystemTimeToFileTime(&sysTime,
3628 (FILETIME *)pvStructInfo);
3633 else
3634 SetLastError(CRYPT_E_ASN1_BADTAG);
3635 return ret;
3638 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3639 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3640 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3642 BOOL ret = FALSE;
3644 __TRY
3646 DWORD bytesNeeded;
3648 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3649 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3650 if (ret)
3652 if (!pvStructInfo)
3653 *pcbStructInfo = bytesNeeded;
3654 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3655 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3657 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3658 pvStructInfo = *(BYTE **)pvStructInfo;
3659 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3660 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3661 &bytesNeeded, NULL);
3665 __EXCEPT_PAGE_FAULT
3667 SetLastError(STATUS_ACCESS_VIOLATION);
3669 __ENDTRY
3670 return ret;
3673 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3674 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3675 DWORD *pcbDecoded)
3677 BOOL ret = FALSE;
3679 if (pbEncoded[0] == ASN_GENERALTIME)
3681 if (cbEncoded <= 1)
3682 SetLastError(CRYPT_E_ASN1_EOD);
3683 else if (pbEncoded[1] > 0x7f)
3685 /* long-form date strings really can't be valid */
3686 SetLastError(CRYPT_E_ASN1_CORRUPT);
3688 else
3690 BYTE len = pbEncoded[1];
3692 if (len < MIN_ENCODED_TIME_LENGTH)
3693 SetLastError(CRYPT_E_ASN1_CORRUPT);
3694 else
3696 SYSTEMTIME sysTime = { 0 };
3698 ret = TRUE;
3699 if (pcbDecoded)
3700 *pcbDecoded = 2 + len;
3701 pbEncoded += 2;
3702 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3703 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3704 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3705 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3706 if (ret && len > 0)
3708 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3709 sysTime.wMinute);
3710 if (ret && len > 0)
3711 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3712 sysTime.wSecond);
3713 if (ret && len > 0 && (*pbEncoded == '.' ||
3714 *pbEncoded == ','))
3716 BYTE digits;
3718 pbEncoded++;
3719 len--;
3720 /* workaround macro weirdness */
3721 digits = min(len, 3);
3722 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3723 sysTime.wMilliseconds);
3725 if (ret)
3726 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3727 &sysTime);
3729 if (ret)
3731 if (!pvStructInfo)
3732 *pcbStructInfo = sizeof(FILETIME);
3733 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3734 sizeof(FILETIME))))
3735 ret = SystemTimeToFileTime(&sysTime,
3736 (FILETIME *)pvStructInfo);
3741 else
3742 SetLastError(CRYPT_E_ASN1_BADTAG);
3743 return ret;
3746 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
3747 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3748 DWORD *pcbDecoded)
3750 BOOL ret;
3751 InternalDecodeFunc decode = NULL;
3753 if (pbEncoded[0] == ASN_UTCTIME)
3754 decode = CRYPT_AsnDecodeUtcTimeInternal;
3755 else if (pbEncoded[0] == ASN_GENERALTIME)
3756 decode = CRYPT_AsnDecodeGeneralizedTime;
3757 if (decode)
3758 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
3759 pcbStructInfo, pcbDecoded);
3760 else
3762 SetLastError(CRYPT_E_ASN1_BADTAG);
3763 ret = FALSE;
3765 return ret;
3768 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3769 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3770 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3772 BOOL ret;
3774 __TRY
3776 DWORD bytesNeeded;
3778 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3779 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3780 if (ret)
3782 if (!pvStructInfo)
3783 *pcbStructInfo = bytesNeeded;
3784 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3785 pvStructInfo, pcbStructInfo, bytesNeeded)))
3787 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3788 pvStructInfo = *(BYTE **)pvStructInfo;
3789 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3790 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3791 &bytesNeeded, NULL);
3795 __EXCEPT_PAGE_FAULT
3797 SetLastError(STATUS_ACCESS_VIOLATION);
3798 ret = FALSE;
3800 __ENDTRY
3801 return ret;
3804 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3805 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3806 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3808 BOOL ret = TRUE;
3810 __TRY
3812 if (pbEncoded[0] == ASN_SEQUENCEOF)
3814 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3816 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3818 BYTE lenBytes;
3819 const BYTE *ptr;
3821 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3822 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3823 cValue = 0;
3824 ptr = pbEncoded + 1 + lenBytes;
3825 remainingLen = dataLen;
3826 while (ret && remainingLen)
3828 DWORD nextLen;
3830 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3831 if (ret)
3833 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3835 remainingLen -= 1 + nextLenBytes + nextLen;
3836 ptr += 1 + nextLenBytes + nextLen;
3837 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3838 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3839 bytesNeeded += 1 + nextLenBytes + nextLen;
3840 cValue++;
3843 if (ret)
3845 CRYPT_SEQUENCE_OF_ANY *seq;
3846 BYTE *nextPtr;
3847 DWORD i;
3849 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3850 pvStructInfo, pcbStructInfo, bytesNeeded)))
3852 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3853 pvStructInfo = *(BYTE **)pvStructInfo;
3854 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3855 seq->cValue = cValue;
3856 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3857 sizeof(*seq));
3858 nextPtr = (BYTE *)seq->rgValue +
3859 cValue * sizeof(CRYPT_DER_BLOB);
3860 ptr = pbEncoded + 1 + lenBytes;
3861 remainingLen = dataLen;
3862 i = 0;
3863 while (ret && remainingLen)
3865 DWORD nextLen;
3867 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3868 if (ret)
3870 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3872 seq->rgValue[i].cbData = 1 + nextLenBytes +
3873 nextLen;
3874 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3875 seq->rgValue[i].pbData = (BYTE *)ptr;
3876 else
3878 seq->rgValue[i].pbData = nextPtr;
3879 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3880 nextLen);
3881 nextPtr += 1 + nextLenBytes + nextLen;
3883 remainingLen -= 1 + nextLenBytes + nextLen;
3884 ptr += 1 + nextLenBytes + nextLen;
3885 i++;
3892 else
3894 SetLastError(CRYPT_E_ASN1_BADTAG);
3895 ret = FALSE;
3898 __EXCEPT_PAGE_FAULT
3900 SetLastError(STATUS_ACCESS_VIOLATION);
3901 ret = FALSE;
3903 __ENDTRY
3904 return ret;
3907 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
3908 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3909 DWORD *pcbDecoded)
3911 BOOL ret;
3913 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3915 DWORD bytesNeeded, dataLen;
3917 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3919 struct AsnArrayDescriptor arrayDesc = {
3920 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3921 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3922 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3923 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3924 DWORD nameLen;
3926 if (dataLen)
3928 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3929 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3930 0, NULL, NULL, &nameLen, NULL, NULL);
3931 /* The CERT_ALT_NAME_INFO's size is included by CRYPT_AsnDecodeArray
3932 * as the sizeof(struct GenericArray), so don't include it in the
3933 * total bytes needed.
3935 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
3936 sizeof(CERT_ALT_NAME_INFO);
3938 else
3939 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3940 if (pcbDecoded)
3941 *pcbDecoded = 1 + lenBytes + dataLen;
3942 if (!pvStructInfo)
3943 *pcbStructInfo = bytesNeeded;
3944 else if (*pcbStructInfo < bytesNeeded)
3946 *pcbStructInfo = bytesNeeded;
3947 SetLastError(ERROR_MORE_DATA);
3948 ret = FALSE;
3950 else
3952 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3954 *pcbStructInfo = bytesNeeded;
3955 if (dataLen)
3957 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3958 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3959 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3960 0, NULL, &name->u.FullName, &nameLen, NULL,
3961 name->u.FullName.rgAltEntry);
3963 else
3964 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3968 else
3970 SetLastError(CRYPT_E_ASN1_BADTAG);
3971 ret = FALSE;
3973 return ret;
3976 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
3977 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3979 struct AsnDecodeSequenceItem items[] = {
3980 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3981 DistPointName), CRYPT_AsnDecodeDistPointName,
3982 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3983 DistPointName.u.FullName.rgAltEntry), 0 },
3984 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3985 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3986 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3987 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3988 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3989 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3991 BOOL ret;
3993 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3994 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3995 pcbDecoded, NULL);
3996 return ret;
3999 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
4000 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4001 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4003 BOOL ret;
4005 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4006 pDecodePara, pvStructInfo, *pcbStructInfo);
4008 __TRY
4010 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4011 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
4012 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
4014 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4015 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4017 __EXCEPT_PAGE_FAULT
4019 SetLastError(STATUS_ACCESS_VIOLATION);
4020 ret = FALSE;
4022 __ENDTRY
4023 return ret;
4026 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
4027 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4028 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4030 BOOL ret;
4032 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4033 pDecodePara, pvStructInfo, *pcbStructInfo);
4035 __TRY
4037 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4038 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4040 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4041 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4043 __EXCEPT_PAGE_FAULT
4045 SetLastError(STATUS_ACCESS_VIOLATION);
4046 ret = FALSE;
4048 __ENDTRY
4049 return ret;
4052 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4053 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4054 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4056 BOOL ret;
4058 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4059 pDecodePara, pvStructInfo, *pcbStructInfo);
4061 __TRY
4063 struct AsnDecodeSequenceItem items[] = {
4064 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4065 DistPointName), CRYPT_AsnDecodeDistPointName,
4066 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4067 offsetof(CRL_ISSUING_DIST_POINT,
4068 DistPointName.u.FullName.rgAltEntry), 0 },
4069 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4070 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4071 FALSE, 0 },
4072 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4073 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4074 FALSE, 0 },
4075 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4076 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4077 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4078 OnlySomeReasonFlags.pbData), 0 },
4079 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4080 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4083 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4084 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4085 pcbStructInfo, NULL, NULL);
4087 __EXCEPT_PAGE_FAULT
4089 SetLastError(STATUS_ACCESS_VIOLATION);
4090 ret = FALSE;
4092 __ENDTRY
4093 return ret;
4096 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
4097 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4098 DWORD *pcbDecoded)
4100 BOOL ret = FALSE;
4102 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4103 pvStructInfo, *pcbStructInfo, pcbDecoded);
4105 if (!cbEncoded)
4107 SetLastError(CRYPT_E_ASN1_EOD);
4108 return FALSE;
4110 if (pbEncoded[0] != (ASN_CONTEXT | 1))
4112 SetLastError(CRYPT_E_ASN1_BADTAG);
4113 return FALSE;
4115 /* The BOOL is implicit: if the integer is present, then it's TRUE */
4116 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
4117 pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo,
4118 pcbDecoded);
4119 if (ret && pvStructInfo)
4120 *(BOOL *)pvStructInfo = TRUE;
4121 TRACE("returning %d\n", ret);
4122 return ret;
4125 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
4126 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4127 DWORD *pcbDecoded)
4129 BOOL ret;
4130 struct AsnDecodeSequenceItem items[] = {
4131 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
4132 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
4133 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
4134 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
4135 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
4136 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
4137 CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0,
4138 0 },
4140 CERT_GENERAL_SUBTREE *subtree = (CERT_GENERAL_SUBTREE *)pvStructInfo;
4142 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4143 pvStructInfo, *pcbStructInfo, pcbDecoded);
4145 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4146 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4147 pcbDecoded, subtree ? (BYTE *)subtree->Base.u.pwszURL : NULL);
4148 if (pcbDecoded)
4150 TRACE("%d\n", *pcbDecoded);
4151 if (*pcbDecoded < cbEncoded)
4152 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
4153 *(pbEncoded + *pcbDecoded + 1));
4155 TRACE("returning %d\n", ret);
4156 return ret;
4159 static BOOL CRYPT_AsnDecodeSubtreeArray(const BYTE *pbEncoded,
4160 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4161 DWORD *pcbDecoded)
4163 BOOL ret = TRUE;
4164 struct AsnArrayDescriptor arrayDesc = { 0,
4165 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4166 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4167 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4169 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4170 pvStructInfo, *pcbStructInfo, pcbDecoded);
4172 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4173 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4174 array ? array->rgItems : NULL);
4175 return ret;
4179 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
4180 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4181 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4183 BOOL ret = FALSE;
4185 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4186 pDecodePara, pvStructInfo, *pcbStructInfo);
4188 __TRY
4190 struct AsnDecodeSequenceItem items[] = {
4191 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4192 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
4193 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4194 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
4195 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
4196 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4197 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4198 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
4201 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4202 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4203 pcbStructInfo, NULL, NULL);
4205 __EXCEPT_PAGE_FAULT
4207 SetLastError(STATUS_ACCESS_VIOLATION);
4209 __ENDTRY
4210 return ret;
4213 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
4214 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4215 DWORD *pcbDecoded)
4217 BOOL ret;
4218 struct AsnDecodeSequenceItem items[] = {
4219 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4220 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4221 Issuer.pbData) },
4222 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4223 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4224 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4226 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4227 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4229 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4230 pvStructInfo, *pcbStructInfo, pcbDecoded);
4232 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4233 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4234 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4235 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4237 SetLastError(CRYPT_E_ASN1_CORRUPT);
4238 ret = FALSE;
4240 TRACE("returning %d\n", ret);
4241 return ret;
4244 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4245 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4246 DWORD *pcbDecoded)
4248 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4249 struct AsnDecodeSequenceItem items[] = {
4250 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4251 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4252 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4253 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4254 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4255 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4256 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4257 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4258 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4259 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4260 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4261 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4262 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4263 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4264 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4265 HashEncryptionAlgorithm.pszObjId), 0 },
4266 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4267 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4268 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4269 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4270 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4271 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4272 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4274 BOOL ret;
4276 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4277 pvStructInfo, *pcbStructInfo);
4279 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4280 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4281 pcbDecoded, info ? info->Issuer.pbData : NULL);
4282 return ret;
4285 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4286 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4287 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4289 BOOL ret = FALSE;
4291 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4292 pDecodePara, pvStructInfo, *pcbStructInfo);
4294 __TRY
4296 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4297 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4298 if (ret && pvStructInfo)
4300 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4301 pcbStructInfo, *pcbStructInfo);
4302 if (ret)
4304 CMSG_SIGNER_INFO *info;
4306 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4307 pvStructInfo = *(BYTE **)pvStructInfo;
4308 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4309 info->Issuer.pbData = ((BYTE *)info +
4310 sizeof(CMSG_SIGNER_INFO));
4311 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4312 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4313 pcbStructInfo, NULL);
4317 __EXCEPT_PAGE_FAULT
4319 SetLastError(STATUS_ACCESS_VIOLATION);
4321 __ENDTRY
4322 TRACE("returning %d\n", ret);
4323 return ret;
4326 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
4327 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4328 DWORD *pcbDecoded)
4330 CERT_ID *id = (CERT_ID *)pvStructInfo;
4331 BOOL ret = FALSE;
4333 if (*pbEncoded == ASN_SEQUENCEOF)
4335 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
4336 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
4337 if (ret)
4339 if (id)
4340 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
4341 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
4342 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4343 sizeof(CERT_ISSUER_SERIAL_NUMBER);
4344 else
4345 *pcbStructInfo = sizeof(CERT_ID);
4348 else if (*pbEncoded == (ASN_CONTEXT | 0))
4350 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
4351 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
4352 if (ret)
4354 if (id)
4355 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
4356 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
4357 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4358 sizeof(CRYPT_DATA_BLOB);
4359 else
4360 *pcbStructInfo = sizeof(CERT_ID);
4363 else
4364 SetLastError(CRYPT_E_ASN1_BADTAG);
4365 return ret;
4368 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
4369 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4370 DWORD *pcbDecoded)
4372 CMSG_CMS_SIGNER_INFO *info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4373 struct AsnDecodeSequenceItem items[] = {
4374 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
4375 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4376 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
4377 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
4378 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
4379 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
4380 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4381 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4382 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4383 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
4384 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4385 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4386 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
4387 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4388 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
4389 HashEncryptionAlgorithm.pszObjId), 0 },
4390 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
4391 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4392 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
4393 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4394 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
4395 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4396 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4398 BOOL ret;
4400 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4401 pvStructInfo, *pcbStructInfo);
4403 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4404 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4405 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
4406 return ret;
4409 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
4410 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4411 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4413 BOOL ret = FALSE;
4415 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4416 pDecodePara, pvStructInfo, *pcbStructInfo);
4418 __TRY
4420 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
4421 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4422 if (ret && pvStructInfo)
4424 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4425 pcbStructInfo, *pcbStructInfo);
4426 if (ret)
4428 CMSG_CMS_SIGNER_INFO *info;
4430 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4431 pvStructInfo = *(BYTE **)pvStructInfo;
4432 info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4433 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
4434 sizeof(CMSG_CMS_SIGNER_INFO));
4435 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
4436 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4437 pcbStructInfo, NULL);
4441 __EXCEPT_PAGE_FAULT
4443 SetLastError(STATUS_ACCESS_VIOLATION);
4445 __ENDTRY
4446 TRACE("returning %d\n", ret);
4447 return ret;
4450 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
4451 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4453 BOOL ret;
4454 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4455 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
4456 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
4457 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4459 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4460 pvStructInfo, *pcbStructInfo, pcbDecoded);
4462 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4463 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4464 array ? array->rgItems : NULL);
4465 return ret;
4468 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4469 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4470 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4472 BOOL ret = FALSE;
4473 struct AsnDecodeSequenceItem items[] = {
4474 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4475 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4476 /* Placeholder for the hash algorithms - redundant with those in the
4477 * signers, so just ignore them.
4479 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4480 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4481 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4482 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4483 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4484 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4485 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4486 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4487 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4488 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4489 sizeof(struct GenericArray), TRUE, TRUE,
4490 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4491 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4492 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4493 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4496 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4497 pDecodePara, signedInfo, *pcbSignedInfo);
4499 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4500 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
4501 NULL, NULL);
4502 TRACE("returning %d\n", ret);
4503 return ret;
4506 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4507 LPCSTR lpszStructType)
4509 CryptDecodeObjectExFunc decodeFunc = NULL;
4511 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4512 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4514 SetLastError(ERROR_FILE_NOT_FOUND);
4515 return NULL;
4517 if (!HIWORD(lpszStructType))
4519 switch (LOWORD(lpszStructType))
4521 case LOWORD(X509_CERT):
4522 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4523 break;
4524 case LOWORD(X509_CERT_TO_BE_SIGNED):
4525 decodeFunc = CRYPT_AsnDecodeCert;
4526 break;
4527 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4528 decodeFunc = CRYPT_AsnDecodeCRL;
4529 break;
4530 case LOWORD(X509_EXTENSIONS):
4531 decodeFunc = CRYPT_AsnDecodeExtensions;
4532 break;
4533 case LOWORD(X509_NAME_VALUE):
4534 decodeFunc = CRYPT_AsnDecodeNameValue;
4535 break;
4536 case LOWORD(X509_NAME):
4537 decodeFunc = CRYPT_AsnDecodeName;
4538 break;
4539 case LOWORD(X509_PUBLIC_KEY_INFO):
4540 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4541 break;
4542 case LOWORD(X509_AUTHORITY_KEY_ID):
4543 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4544 break;
4545 case LOWORD(X509_ALTERNATE_NAME):
4546 decodeFunc = CRYPT_AsnDecodeAltName;
4547 break;
4548 case LOWORD(X509_BASIC_CONSTRAINTS):
4549 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4550 break;
4551 case LOWORD(X509_BASIC_CONSTRAINTS2):
4552 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4553 break;
4554 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4555 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4556 break;
4557 case LOWORD(X509_UNICODE_NAME):
4558 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4559 break;
4560 case LOWORD(PKCS_ATTRIBUTE):
4561 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4562 break;
4563 case LOWORD(X509_UNICODE_NAME_VALUE):
4564 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4565 break;
4566 case LOWORD(X509_OCTET_STRING):
4567 decodeFunc = CRYPT_AsnDecodeOctets;
4568 break;
4569 case LOWORD(X509_BITS):
4570 case LOWORD(X509_KEY_USAGE):
4571 decodeFunc = CRYPT_AsnDecodeBits;
4572 break;
4573 case LOWORD(X509_INTEGER):
4574 decodeFunc = CRYPT_AsnDecodeInt;
4575 break;
4576 case LOWORD(X509_MULTI_BYTE_INTEGER):
4577 decodeFunc = CRYPT_AsnDecodeInteger;
4578 break;
4579 case LOWORD(X509_MULTI_BYTE_UINT):
4580 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4581 break;
4582 case LOWORD(X509_ENUMERATED):
4583 decodeFunc = CRYPT_AsnDecodeEnumerated;
4584 break;
4585 case LOWORD(X509_CHOICE_OF_TIME):
4586 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4587 break;
4588 case LOWORD(X509_AUTHORITY_KEY_ID2):
4589 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4590 break;
4591 case LOWORD(PKCS_CONTENT_INFO):
4592 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4593 break;
4594 case LOWORD(X509_SEQUENCE_OF_ANY):
4595 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4596 break;
4597 case LOWORD(PKCS_UTC_TIME):
4598 decodeFunc = CRYPT_AsnDecodeUtcTime;
4599 break;
4600 case LOWORD(X509_CRL_DIST_POINTS):
4601 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4602 break;
4603 case LOWORD(X509_ENHANCED_KEY_USAGE):
4604 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4605 break;
4606 case LOWORD(PKCS_ATTRIBUTES):
4607 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4608 break;
4609 case LOWORD(X509_ISSUING_DIST_POINT):
4610 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4611 break;
4612 case LOWORD(X509_NAME_CONSTRAINTS):
4613 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4614 break;
4615 case LOWORD(PKCS7_SIGNER_INFO):
4616 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4617 break;
4618 case LOWORD(CMS_SIGNER_INFO):
4619 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
4620 break;
4623 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4624 decodeFunc = CRYPT_AsnDecodeExtensions;
4625 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4626 decodeFunc = CRYPT_AsnDecodeUtcTime;
4627 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4628 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4629 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4630 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4631 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4632 decodeFunc = CRYPT_AsnDecodeEnumerated;
4633 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4634 decodeFunc = CRYPT_AsnDecodeBits;
4635 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4636 decodeFunc = CRYPT_AsnDecodeOctets;
4637 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4638 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4639 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4640 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4641 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4642 decodeFunc = CRYPT_AsnDecodeAltName;
4643 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4644 decodeFunc = CRYPT_AsnDecodeAltName;
4645 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4646 decodeFunc = CRYPT_AsnDecodeAltName;
4647 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4648 decodeFunc = CRYPT_AsnDecodeAltName;
4649 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4650 decodeFunc = CRYPT_AsnDecodeAltName;
4651 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4652 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4653 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4654 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4655 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4656 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4657 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4658 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4659 return decodeFunc;
4662 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4663 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4665 static HCRYPTOIDFUNCSET set = NULL;
4666 CryptDecodeObjectFunc decodeFunc = NULL;
4668 if (!set)
4669 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4670 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4671 (void **)&decodeFunc, hFunc);
4672 return decodeFunc;
4675 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4676 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4678 static HCRYPTOIDFUNCSET set = NULL;
4679 CryptDecodeObjectExFunc decodeFunc = NULL;
4681 if (!set)
4682 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4683 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4684 (void **)&decodeFunc, hFunc);
4685 return decodeFunc;
4688 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4689 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4690 DWORD *pcbStructInfo)
4692 BOOL ret = FALSE;
4693 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4694 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4695 HCRYPTOIDFUNCADDR hFunc = NULL;
4697 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4698 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4699 pvStructInfo, pcbStructInfo);
4701 if (!pvStructInfo && !pcbStructInfo)
4703 SetLastError(ERROR_INVALID_PARAMETER);
4704 return FALSE;
4706 if (!cbEncoded)
4708 SetLastError(CRYPT_E_ASN1_EOD);
4709 return FALSE;
4711 if (cbEncoded > MAX_ENCODED_LEN)
4713 SetLastError(CRYPT_E_ASN1_LARGE);
4714 return FALSE;
4717 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4718 lpszStructType)))
4720 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4721 debugstr_a(lpszStructType));
4722 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4723 lpszStructType, &hFunc);
4724 if (!pCryptDecodeObject)
4725 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4726 lpszStructType, &hFunc);
4728 if (pCryptDecodeObject)
4729 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4730 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4731 else if (pCryptDecodeObjectEx)
4732 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4733 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4734 pvStructInfo, pcbStructInfo);
4735 if (hFunc)
4736 CryptFreeOIDFunctionAddress(hFunc, 0);
4737 TRACE_(crypt)("returning %d\n", ret);
4738 return ret;
4741 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4742 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4743 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4745 BOOL ret = FALSE;
4746 CryptDecodeObjectExFunc decodeFunc;
4747 HCRYPTOIDFUNCADDR hFunc = NULL;
4749 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4750 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4751 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4753 if (!pvStructInfo && !pcbStructInfo)
4755 SetLastError(ERROR_INVALID_PARAMETER);
4756 return FALSE;
4758 if (!cbEncoded)
4760 SetLastError(CRYPT_E_ASN1_EOD);
4761 return FALSE;
4763 if (cbEncoded > MAX_ENCODED_LEN)
4765 SetLastError(CRYPT_E_ASN1_LARGE);
4766 return FALSE;
4769 SetLastError(NOERROR);
4770 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4771 *(BYTE **)pvStructInfo = NULL;
4772 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4773 if (!decodeFunc)
4775 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4776 debugstr_a(lpszStructType));
4777 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4778 &hFunc);
4780 if (decodeFunc)
4781 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4782 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4783 else
4785 CryptDecodeObjectFunc pCryptDecodeObject =
4786 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4788 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4789 * directly, as that could cause an infinite loop.
4791 if (pCryptDecodeObject)
4793 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4795 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4796 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4797 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4798 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4799 ret = pCryptDecodeObject(dwCertEncodingType,
4800 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4801 *(BYTE **)pvStructInfo, pcbStructInfo);
4803 else
4804 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4805 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4808 if (hFunc)
4809 CryptFreeOIDFunctionAddress(hFunc, 0);
4810 TRACE_(crypt)("returning %d\n", ret);
4811 return ret;