Release 0.9.14.
[wine/multimedia.git] / dlls / crypt32 / decode.c
blobe6e2423cde884176b2471dd11b1ecafbc5e59c81
1 /*
2 * Copyright 2005 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface is
21 * undocumented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially:
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
34 #include <assert.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
39 #define NONAMELESSUNION
41 #include "windef.h"
42 #include "winbase.h"
43 #include "excpt.h"
44 #include "wincrypt.h"
45 #include "winreg.h"
46 #include "snmp.h"
47 #include "wine/debug.h"
48 #include "wine/exception.h"
49 #include "crypt32_private.h"
51 /* This is a bit arbitrary, but to set some limit: */
52 #define MAX_ENCODED_LEN 0x02000000
54 #define ASN_FLAGS_MASK 0xe0
55 #define ASN_TYPE_MASK 0x1f
57 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
59 struct GenericArray
61 DWORD cItems;
62 BYTE *rgItems;
65 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
66 DWORD, DWORD, void *, DWORD *);
67 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
68 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
70 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
71 * The dwCertEncodingType and lpszStructType are ignored by the built-in
72 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
73 * since it must call functions in external DLLs that follow these signatures.
75 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
76 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
77 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
78 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
79 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
80 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
81 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
82 * time, doesn't do memory allocation, and doesn't do exception handling.
83 * (This isn't intended to be the externally-called one.)
85 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
86 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
87 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
88 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
89 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
90 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
91 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
92 /* Internal function */
93 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
94 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
95 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
96 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
97 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
98 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
99 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
100 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
101 * member has been initialized, doesn't do exception handling, and doesn't do
102 * memory allocation.
104 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
105 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
106 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
107 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
108 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
109 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
110 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
111 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
112 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
113 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
114 * member has been initialized, doesn't do exception handling, and doesn't do
115 * memory allocation.
117 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
118 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
119 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
120 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
121 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
122 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
123 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
124 void *pvStructInfo, DWORD *pcbStructInfo);
126 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
127 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
128 DWORD *pcbStructInfo)
130 static HCRYPTOIDFUNCSET set = NULL;
131 BOOL ret = FALSE;
132 CryptDecodeObjectFunc pCryptDecodeObject;
133 HCRYPTOIDFUNCADDR hFunc;
135 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p)\n", dwCertEncodingType,
136 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
137 pvStructInfo, pcbStructInfo);
139 if (!pvStructInfo && !pcbStructInfo)
141 SetLastError(ERROR_INVALID_PARAMETER);
142 return FALSE;
145 /* Try registered DLL first.. */
146 if (!set)
147 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
148 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
149 (void **)&pCryptDecodeObject, &hFunc);
150 if (pCryptDecodeObject)
152 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
153 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
154 CryptFreeOIDFunctionAddress(hFunc, 0);
156 else
158 /* If not, use CryptDecodeObjectEx */
159 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
160 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
162 return ret;
165 /* Gets the number of length bytes from the given (leading) length byte */
166 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
168 /* Helper function to get the encoded length of the data starting at pbEncoded,
169 * where pbEncoded[0] is the tag. If the data are too short to contain a
170 * length or if the length is too large for cbEncoded, sets an appropriate
171 * error code and returns FALSE.
173 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
174 DWORD *len)
176 BOOL ret;
178 if (cbEncoded <= 1)
180 SetLastError(CRYPT_E_ASN1_CORRUPT);
181 ret = FALSE;
183 else if (pbEncoded[1] <= 0x7f)
185 if (pbEncoded[1] + 1 > cbEncoded)
187 SetLastError(CRYPT_E_ASN1_EOD);
188 ret = FALSE;
190 else
192 *len = pbEncoded[1];
193 ret = TRUE;
196 else
198 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
200 if (lenLen > sizeof(DWORD) + 1)
202 SetLastError(CRYPT_E_ASN1_LARGE);
203 ret = FALSE;
205 else if (lenLen + 2 > cbEncoded)
207 SetLastError(CRYPT_E_ASN1_CORRUPT);
208 ret = FALSE;
210 else
212 DWORD out = 0;
214 pbEncoded += 2;
215 while (--lenLen)
217 out <<= 8;
218 out |= *pbEncoded++;
220 if (out + lenLen + 1 > cbEncoded)
222 SetLastError(CRYPT_E_ASN1_EOD);
223 ret = FALSE;
225 else
227 *len = out;
228 ret = TRUE;
232 return ret;
235 /* Helper function to check *pcbStructInfo, set it to the required size, and
236 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
237 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
238 * pointer to the newly allocated memory.
240 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
241 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
242 DWORD bytesNeeded)
244 BOOL ret = TRUE;
246 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
248 if (pDecodePara && pDecodePara->pfnAlloc)
249 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
250 else
251 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
252 if (!*(BYTE **)pvStructInfo)
253 ret = FALSE;
254 else
255 *pcbStructInfo = bytesNeeded;
257 else if (*pcbStructInfo < bytesNeeded)
259 *pcbStructInfo = bytesNeeded;
260 SetLastError(ERROR_MORE_DATA);
261 ret = FALSE;
263 return ret;
266 /* tag:
267 * The expected tag of the item. If tag is 0, decodeFunc is called
268 * regardless of the tag value seen.
269 * offset:
270 * A sequence is decoded into a struct. The offset member is the
271 * offset of this item within that struct.
272 * decodeFunc:
273 * The decoder function to use. If this is NULL, then the member isn't
274 * decoded, but minSize space is reserved for it.
275 * minSize:
276 * The minimum amount of space occupied after decoding. You must set this.
277 * optional:
278 * If true, and the tag doesn't match the expected tag for this item,
279 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
280 * filled with 0 for this member.
281 * hasPointer, pointerOffset, minSize:
282 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
283 * the offset within the (outer) struct of the data pointer (or to the
284 * first data pointer, if more than one exist).
285 * size:
286 * Used by CRYPT_AsnDecodeSequence, not for your use.
288 struct AsnDecodeSequenceItem
290 BYTE tag;
291 DWORD offset;
292 CryptDecodeObjectExFunc decodeFunc;
293 DWORD minSize;
294 BOOL optional;
295 BOOL hasPointer;
296 DWORD pointerOffset;
297 DWORD size;
300 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
301 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
302 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData)
304 BOOL ret;
305 DWORD i;
306 const BYTE *ptr;
308 ptr = pbEncoded + 1 + GET_LEN_BYTES(pbEncoded[1]);
309 for (i = 0, ret = TRUE; ret && i < cItem; i++)
311 if (cbEncoded - (ptr - pbEncoded) != 0)
313 DWORD nextItemLen;
315 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
316 &nextItemLen)))
318 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
320 if (ptr[0] == items[i].tag || !items[i].tag)
322 if (nextData && pvStructInfo && items[i].hasPointer)
324 TRACE("Setting next pointer to %p\n",
325 nextData);
326 *(BYTE **)((BYTE *)pvStructInfo +
327 items[i].pointerOffset) = nextData;
329 if (items[i].decodeFunc)
331 if (pvStructInfo)
332 TRACE("decoding item %ld\n", i);
333 else
334 TRACE("sizing item %ld\n", i);
335 ret = items[i].decodeFunc(dwCertEncodingType,
336 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
337 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
338 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
339 : NULL, &items[i].size);
340 if (ret)
342 if (nextData && items[i].hasPointer &&
343 items[i].size > items[i].minSize)
345 nextData += items[i].size - items[i].minSize;
346 /* align nextData to DWORD boundaries */
347 if (items[i].size % sizeof(DWORD))
348 nextData += sizeof(DWORD) - items[i].size %
349 sizeof(DWORD);
351 /* Account for alignment padding */
352 if (items[i].size % sizeof(DWORD))
353 items[i].size += sizeof(DWORD) -
354 items[i].size % sizeof(DWORD);
355 ptr += 1 + nextItemLenBytes + nextItemLen;
357 else if (items[i].optional &&
358 GetLastError() == CRYPT_E_ASN1_BADTAG)
360 TRACE("skipping optional item %ld\n", i);
361 items[i].size = items[i].minSize;
362 SetLastError(NOERROR);
363 ret = TRUE;
365 else
366 TRACE("item %ld failed: %08lx\n", i,
367 GetLastError());
369 else
370 items[i].size = items[i].minSize;
372 else if (items[i].optional)
374 TRACE("skipping optional item %ld\n", i);
375 items[i].size = items[i].minSize;
377 else
379 TRACE("tag %02x doesn't match expected %02x\n",
380 ptr[0], items[i].tag);
381 SetLastError(CRYPT_E_ASN1_BADTAG);
382 ret = FALSE;
386 else if (items[i].optional)
388 TRACE("missing optional item %ld, skipping\n", i);
389 items[i].size = items[i].minSize;
391 else
393 TRACE("not enough bytes for item %ld, failing\n", i);
394 SetLastError(CRYPT_E_ASN1_CORRUPT);
395 ret = FALSE;
398 if (cbEncoded - (ptr - pbEncoded) != 0)
400 TRACE("%ld remaining bytes, failing\n", cbEncoded -
401 (ptr - pbEncoded));
402 SetLastError(CRYPT_E_ASN1_CORRUPT);
403 ret = FALSE;
405 return ret;
408 /* This decodes an arbitrary sequence into a contiguous block of memory
409 * (basically, a struct.) Each element being decoded is described by a struct
410 * AsnDecodeSequenceItem, see above.
411 * startingPointer is an optional pointer to the first place where dynamic
412 * data will be stored. If you know the starting offset, you may pass it
413 * here. Otherwise, pass NULL, and one will be inferred from the items.
414 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
415 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
417 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
418 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
419 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
420 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
422 BOOL ret;
424 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded,
425 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
426 startingPointer);
428 if (pbEncoded[0] == ASN_SEQUENCE)
430 DWORD dataLen;
432 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
434 DWORD i;
436 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
437 cbEncoded, dwFlags, NULL, NULL);
438 if (ret)
440 DWORD bytesNeeded = 0, structSize = 0;
442 for (i = 0; i < cItem; i++)
444 bytesNeeded += items[i].size;
445 structSize += items[i].minSize;
447 if (!pvStructInfo)
448 *pcbStructInfo = bytesNeeded;
449 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
450 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
452 BYTE *nextData;
454 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
455 pvStructInfo = *(BYTE **)pvStructInfo;
456 if (startingPointer)
457 nextData = (BYTE *)startingPointer;
458 else
459 nextData = (BYTE *)pvStructInfo + structSize;
460 memset(pvStructInfo, 0, structSize);
461 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
462 pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
467 else
469 SetLastError(CRYPT_E_ASN1_BADTAG);
470 ret = FALSE;
472 TRACE("returning %d (%08lx)\n", ret, GetLastError());
473 return ret;
476 /* tag:
477 * The expected tag of the entire encoded array (usually a variant
478 * of ASN_SETOF or ASN_SEQUENCEOF.)
479 * decodeFunc:
480 * used to decode each item in the array
481 * itemSize:
482 * is the minimum size of each decoded item
483 * hasPointer:
484 * indicates whether each item has a dynamic pointer
485 * pointerOffset:
486 * indicates the offset within itemSize at which the pointer exists
488 struct AsnArrayDescriptor
490 BYTE tag;
491 CryptDecodeObjectExFunc decodeFunc;
492 DWORD itemSize;
493 BOOL hasPointer;
494 DWORD pointerOffset;
497 struct AsnArrayItemSize
499 DWORD encodedLen;
500 DWORD size;
503 /* Decodes an array of like types into a struct GenericArray.
504 * The layout and decoding of the array are described by a struct
505 * AsnArrayDescriptor.
507 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
508 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
509 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
510 void *startingPointer)
512 BOOL ret = TRUE;
514 TRACE("%p, %p, %ld, %08lx, %p, %p, %ld, %p\n", arrayDesc, pbEncoded,
515 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
516 startingPointer);
518 if (pbEncoded[0] == arrayDesc->tag)
520 DWORD dataLen;
522 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
524 DWORD bytesNeeded, cItems = 0;
525 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
526 /* There can be arbitrarily many items, but there is often only one.
528 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
530 bytesNeeded = sizeof(struct GenericArray);
531 if (dataLen)
533 const BYTE *ptr;
535 for (ptr = pbEncoded + 1 + lenBytes; ret &&
536 ptr - pbEncoded - 1 - lenBytes < dataLen; )
538 DWORD itemLenBytes, itemDataLen, size;
540 itemLenBytes = GET_LEN_BYTES(ptr[1]);
541 /* Each item decoded may not tolerate extraneous bytes, so
542 * get the length of the next element and pass it directly.
544 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
545 &itemDataLen);
546 if (ret)
547 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
548 1 + itemLenBytes + itemDataLen,
549 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
550 &size);
551 if (ret)
553 DWORD nextLen;
555 cItems++;
556 if (itemSizes != &itemSize)
557 itemSizes = CryptMemRealloc(itemSizes,
558 cItems * sizeof(struct AsnArrayItemSize));
559 else
561 itemSizes =
562 CryptMemAlloc(
563 cItems * sizeof(struct AsnArrayItemSize));
564 memcpy(itemSizes, &itemSize, sizeof(itemSize));
566 if (itemSizes)
568 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
569 + itemDataLen;
570 itemSizes[cItems - 1].size = size;
571 bytesNeeded += size;
572 ret = CRYPT_GetLen(ptr,
573 cbEncoded - (ptr - pbEncoded), &nextLen);
574 if (ret)
575 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
577 else
578 ret = FALSE;
582 if (ret)
584 if (!pvStructInfo)
585 *pcbStructInfo = bytesNeeded;
586 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
587 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
589 DWORD i;
590 BYTE *nextData;
591 const BYTE *ptr;
592 struct GenericArray *array;
594 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
595 pvStructInfo = *(BYTE **)pvStructInfo;
596 array = (struct GenericArray *)pvStructInfo;
597 array->cItems = cItems;
598 if (startingPointer)
599 array->rgItems = startingPointer;
600 else
601 array->rgItems = (BYTE *)array +
602 sizeof(struct GenericArray);
603 nextData = (BYTE *)array->rgItems +
604 array->cItems * arrayDesc->itemSize;
605 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
606 i < cItems && ptr - pbEncoded - 1 - lenBytes <
607 dataLen; i++)
609 if (arrayDesc->hasPointer)
610 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
611 + arrayDesc->pointerOffset) = nextData;
612 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
613 itemSizes[i].encodedLen,
614 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
615 array->rgItems + i * arrayDesc->itemSize,
616 &itemSizes[i].size);
617 if (ret)
619 DWORD nextLen;
621 nextData += itemSizes[i].size - arrayDesc->itemSize;
622 ret = CRYPT_GetLen(ptr,
623 cbEncoded - (ptr - pbEncoded), &nextLen);
624 if (ret)
625 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
630 if (itemSizes != &itemSize)
631 CryptMemFree(itemSizes);
634 else
636 SetLastError(CRYPT_E_ASN1_BADTAG);
637 ret = FALSE;
639 return ret;
642 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
643 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
644 * to CRYPT_E_ASN1_CORRUPT.
645 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
646 * set!
648 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
649 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
650 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
652 BOOL ret;
653 DWORD dataLen;
655 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
657 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
658 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
660 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
661 bytesNeeded += 1 + lenBytes + dataLen;
663 if (!pvStructInfo)
664 *pcbStructInfo = bytesNeeded;
665 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
666 pvStructInfo, pcbStructInfo, bytesNeeded)))
668 CRYPT_DER_BLOB *blob;
670 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
671 pvStructInfo = *(BYTE **)pvStructInfo;
672 blob = (CRYPT_DER_BLOB *)pvStructInfo;
673 blob->cbData = 1 + lenBytes + dataLen;
674 if (blob->cbData)
676 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
677 blob->pbData = (BYTE *)pbEncoded;
678 else
680 assert(blob->pbData);
681 memcpy(blob->pbData, pbEncoded, blob->cbData);
684 else
686 SetLastError(CRYPT_E_ASN1_CORRUPT);
687 ret = FALSE;
691 return ret;
694 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
695 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
696 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
697 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
699 BOOL ret;
701 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
702 pDecodePara, pvStructInfo, *pcbStructInfo);
704 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
705 * place.
707 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
708 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
709 pvStructInfo, pcbStructInfo);
710 if (ret && pvStructInfo)
712 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
714 if (blob->cbData)
716 DWORD i;
717 BYTE temp;
719 for (i = 0; i < blob->cbData / 2; i++)
721 temp = blob->pbData[i];
722 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
723 blob->pbData[blob->cbData - i - 1] = temp;
727 TRACE("returning %d (%08lx)\n", ret, GetLastError());
728 return ret;
731 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
732 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
733 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
735 BOOL ret = TRUE;
737 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
738 pDecodePara, pvStructInfo, *pcbStructInfo);
740 __TRY
742 struct AsnDecodeSequenceItem items[] = {
743 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
744 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
745 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
746 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
747 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
748 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
749 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
750 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
751 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
752 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
755 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
756 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
757 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
758 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
759 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
761 __EXCEPT_PAGE_FAULT
763 SetLastError(STATUS_ACCESS_VIOLATION);
764 ret = FALSE;
766 __ENDTRY
767 return ret;
770 /* Internal function */
771 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
772 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
773 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
775 BOOL ret;
776 DWORD dataLen;
778 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
780 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
782 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
783 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
784 pvStructInfo, pcbStructInfo);
786 return ret;
789 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
790 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
791 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
793 BOOL ret;
795 struct AsnDecodeSequenceItem items[] = {
796 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
797 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
798 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
799 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
802 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
803 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
804 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
805 return ret;
808 /* Internal function */
809 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
810 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
811 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
813 BOOL ret;
814 DWORD dataLen;
816 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
818 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
820 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
821 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
822 pDecodePara, pvStructInfo, pcbStructInfo);
824 return ret;
827 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
828 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
829 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
831 BOOL ret = TRUE;
833 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
834 pDecodePara, pvStructInfo, *pcbStructInfo);
836 __TRY
838 struct AsnDecodeSequenceItem items[] = {
839 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
840 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
841 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
842 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
843 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
844 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
845 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
846 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
847 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
848 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
849 Issuer.pbData) },
850 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
851 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
852 FALSE, 0 },
853 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
854 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
855 Subject.pbData) },
856 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
857 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
858 FALSE, TRUE, offsetof(CERT_INFO,
859 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
860 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
861 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
862 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
863 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
864 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
865 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
866 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
867 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
868 offsetof(CERT_INFO, rgExtension), 0 },
871 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
872 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
873 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
875 __EXCEPT_PAGE_FAULT
877 SetLastError(STATUS_ACCESS_VIOLATION);
878 ret = FALSE;
880 __ENDTRY
881 return ret;
884 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
885 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
886 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
888 BOOL ret;
889 struct AsnDecodeSequenceItem items[] = {
890 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
891 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
892 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
893 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
894 sizeof(FILETIME), FALSE, FALSE, 0 },
895 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
896 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
897 offsetof(CRL_ENTRY, rgExtension), 0 },
899 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
901 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
902 *pcbStructInfo);
904 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
905 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
906 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
907 return ret;
910 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
911 * been set prior to calling.
913 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
914 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
915 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
917 BOOL ret;
918 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
919 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
920 offsetof(CRL_ENTRY, SerialNumber.pbData) };
921 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
923 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
924 pDecodePara, pvStructInfo, *pcbStructInfo);
926 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
927 pDecodePara, pvStructInfo, pcbStructInfo,
928 entries ? entries->rgItems : NULL);
929 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
930 return ret;
933 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
934 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
935 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
937 BOOL ret = TRUE;
939 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
940 pDecodePara, pvStructInfo, *pcbStructInfo);
942 __TRY
944 struct AsnDecodeSequenceItem items[] = {
945 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CRL_INFO, dwVersion),
946 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
947 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
948 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
949 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
950 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
951 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
952 Issuer.pbData) },
953 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
954 sizeof(FILETIME), FALSE, FALSE, 0 },
955 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
956 sizeof(FILETIME), TRUE, FALSE, 0 },
957 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
958 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
959 offsetof(CRL_INFO, rgCRLEntry), 0 },
960 /* Note that the extensions are ignored by MS, so I'll ignore them too
962 { 0, offsetof(CRL_INFO, cExtension), NULL,
963 sizeof(CERT_EXTENSIONS), TRUE, FALSE, 0 },
966 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
967 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
968 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
970 __EXCEPT_PAGE_FAULT
972 SetLastError(STATUS_ACCESS_VIOLATION);
973 ret = FALSE;
975 __ENDTRY
977 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
978 return ret;
981 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
982 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
983 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
985 BOOL ret = TRUE;
987 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
988 pDecodePara, pvStructInfo, *pcbStructInfo);
990 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
992 DWORD dataLen;
994 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
996 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
997 DWORD bytesNeeded = sizeof(LPSTR);
999 if (dataLen)
1001 /* The largest possible string for the first two components
1002 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1004 char firstTwo[6];
1005 const BYTE *ptr;
1007 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1008 pbEncoded[1 + lenBytes] / 40,
1009 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1010 * 40);
1011 bytesNeeded += strlen(firstTwo) + 1;
1012 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1013 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1015 /* large enough for ".4000000" */
1016 char str[9];
1017 int val = 0;
1019 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1020 (*ptr & 0x80))
1022 val <<= 7;
1023 val |= *ptr & 0x7f;
1024 ptr++;
1026 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1027 (*ptr & 0x80))
1029 SetLastError(CRYPT_E_ASN1_CORRUPT);
1030 ret = FALSE;
1032 else
1034 val <<= 7;
1035 val |= *ptr++;
1036 snprintf(str, sizeof(str), ".%d", val);
1037 bytesNeeded += strlen(str);
1041 if (!pvStructInfo)
1042 *pcbStructInfo = bytesNeeded;
1043 else if (*pcbStructInfo < bytesNeeded)
1045 *pcbStructInfo = bytesNeeded;
1046 SetLastError(ERROR_MORE_DATA);
1047 ret = FALSE;
1049 else
1051 if (dataLen)
1053 const BYTE *ptr;
1054 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1056 *pszObjId = 0;
1057 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1058 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1059 40) * 40);
1060 pszObjId += strlen(pszObjId);
1061 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1062 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1064 int val = 0;
1066 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1067 (*ptr & 0x80))
1069 val <<= 7;
1070 val |= *ptr & 0x7f;
1071 ptr++;
1073 val <<= 7;
1074 val |= *ptr++;
1075 sprintf(pszObjId, ".%d", val);
1076 pszObjId += strlen(pszObjId);
1079 else
1080 *(LPSTR *)pvStructInfo = NULL;
1081 *pcbStructInfo = bytesNeeded;
1085 return ret;
1088 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1089 * ahead of time!
1091 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1092 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1093 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1095 struct AsnDecodeSequenceItem items[] = {
1096 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1097 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1098 offsetof(CERT_EXTENSION, pszObjId), 0 },
1099 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1100 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1101 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1102 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1103 offsetof(CERT_EXTENSION, Value.pbData) },
1105 BOOL ret = TRUE;
1106 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1108 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
1109 *pcbStructInfo);
1111 if (ext)
1112 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1113 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1114 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1115 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1116 if (ext)
1117 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1118 debugstr_a(ext->pszObjId));
1119 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1120 return ret;
1123 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1124 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1125 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1127 BOOL ret = TRUE;
1128 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1129 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1130 offsetof(CERT_EXTENSION, pszObjId) };
1131 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1133 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1134 pDecodePara, pvStructInfo, *pcbStructInfo);
1136 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1137 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1138 return ret;
1141 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1142 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1143 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1145 BOOL ret = TRUE;
1147 __TRY
1149 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1150 lpszStructType, pbEncoded, cbEncoded,
1151 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1152 if (ret && pvStructInfo)
1154 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1155 pcbStructInfo, *pcbStructInfo);
1156 if (ret)
1158 CERT_EXTENSIONS *exts;
1160 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1161 pvStructInfo = *(BYTE **)pvStructInfo;
1162 exts = (CERT_EXTENSIONS *)pvStructInfo;
1163 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1164 sizeof(CERT_EXTENSIONS));
1165 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1166 lpszStructType, pbEncoded, cbEncoded,
1167 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1168 pcbStructInfo);
1172 __EXCEPT_PAGE_FAULT
1174 SetLastError(STATUS_ACCESS_VIOLATION);
1175 ret = FALSE;
1177 __ENDTRY
1178 return ret;
1181 /* Warning: this assumes the address of value->Value.pbData is already set, in
1182 * order to avoid overwriting memory. (In some cases, it may change it, if it
1183 * doesn't copy anything to memory.) Be sure to set it correctly!
1185 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1186 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1187 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1189 BOOL ret = TRUE;
1191 __TRY
1193 DWORD dataLen;
1194 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1196 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1198 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1200 switch (pbEncoded[0])
1202 case ASN_NUMERICSTRING:
1203 case ASN_PRINTABLESTRING:
1204 case ASN_IA5STRING:
1205 break;
1206 default:
1207 FIXME("Unimplemented string type %02x\n", pbEncoded[0]);
1208 SetLastError(OSS_UNIMPLEMENTED);
1209 ret = FALSE;
1211 if (ret)
1213 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE);
1215 switch (pbEncoded[0])
1217 case ASN_NUMERICSTRING:
1218 case ASN_PRINTABLESTRING:
1219 case ASN_IA5STRING:
1220 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1221 bytesNeeded += dataLen;
1222 break;
1224 if (!value)
1225 *pcbStructInfo = bytesNeeded;
1226 else if (*pcbStructInfo < bytesNeeded)
1228 *pcbStructInfo = bytesNeeded;
1229 SetLastError(ERROR_MORE_DATA);
1230 ret = FALSE;
1232 else
1234 *pcbStructInfo = bytesNeeded;
1235 switch (pbEncoded[0])
1237 case ASN_NUMERICSTRING:
1238 value->dwValueType = CERT_RDN_NUMERIC_STRING;
1239 break;
1240 case ASN_PRINTABLESTRING:
1241 value->dwValueType = CERT_RDN_PRINTABLE_STRING;
1242 break;
1243 case ASN_IA5STRING:
1244 value->dwValueType = CERT_RDN_IA5_STRING;
1245 break;
1247 if (dataLen)
1249 switch (pbEncoded[0])
1251 case ASN_NUMERICSTRING:
1252 case ASN_PRINTABLESTRING:
1253 case ASN_IA5STRING:
1254 value->Value.cbData = dataLen;
1255 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1256 value->Value.pbData = (BYTE *)pbEncoded + 1 +
1257 lenBytes;
1258 else
1260 assert(value->Value.pbData);
1261 memcpy(value->Value.pbData,
1262 pbEncoded + 1 + lenBytes, dataLen);
1264 break;
1267 else
1269 value->Value.cbData = 0;
1270 value->Value.pbData = NULL;
1276 __EXCEPT_PAGE_FAULT
1278 SetLastError(STATUS_ACCESS_VIOLATION);
1279 ret = FALSE;
1281 __ENDTRY
1282 return ret;
1285 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1286 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1287 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1289 BOOL ret;
1291 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1292 pvStructInfo, *pcbStructInfo);
1294 __TRY
1296 struct AsnDecodeSequenceItem items[] = {
1297 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1298 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1299 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1300 { 0, offsetof(CERT_RDN_ATTR, dwValueType), CRYPT_AsnDecodeNameValue,
1301 sizeof(CERT_NAME_VALUE), FALSE, TRUE, offsetof(CERT_RDN_ATTR,
1302 Value.pbData), 0 },
1304 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1306 if (attr)
1307 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1308 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1309 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1310 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1311 if (attr)
1313 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1314 debugstr_a(attr->pszObjId));
1315 TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1317 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1319 __EXCEPT_PAGE_FAULT
1321 SetLastError(STATUS_ACCESS_VIOLATION);
1322 ret = FALSE;
1324 __ENDTRY
1325 return ret;
1328 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1329 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1330 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1332 BOOL ret = TRUE;
1334 __TRY
1336 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1337 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1338 offsetof(CERT_RDN_ATTR, pszObjId) };
1339 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1341 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1342 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1344 __EXCEPT_PAGE_FAULT
1346 SetLastError(STATUS_ACCESS_VIOLATION);
1347 ret = FALSE;
1349 __ENDTRY
1350 return ret;
1353 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1354 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1355 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1357 BOOL ret = TRUE;
1359 __TRY
1361 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1362 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1363 offsetof(CERT_RDN, rgRDNAttr) };
1365 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1366 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1368 __EXCEPT_PAGE_FAULT
1370 SetLastError(STATUS_ACCESS_VIOLATION);
1371 ret = FALSE;
1373 __ENDTRY
1374 return ret;
1377 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1378 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1379 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1381 BOOL ret = TRUE;
1382 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1384 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1385 pDecodePara, pvStructInfo, *pcbStructInfo);
1387 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1388 bytesNeeded += cbEncoded;
1389 if (!pvStructInfo)
1390 *pcbStructInfo = bytesNeeded;
1391 else if (*pcbStructInfo < bytesNeeded)
1393 SetLastError(ERROR_MORE_DATA);
1394 *pcbStructInfo = bytesNeeded;
1395 ret = FALSE;
1397 else
1399 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1401 *pcbStructInfo = bytesNeeded;
1402 blob->cbData = cbEncoded;
1403 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1404 blob->pbData = (LPBYTE)pbEncoded;
1405 else
1407 assert(blob->pbData);
1408 memcpy(blob->pbData, pbEncoded, blob->cbData);
1411 return ret;
1414 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1415 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1416 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1418 CRYPT_ALGORITHM_IDENTIFIER *algo =
1419 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1420 BOOL ret = TRUE;
1421 struct AsnDecodeSequenceItem items[] = {
1422 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1423 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1424 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1425 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1426 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1427 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1430 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1431 pDecodePara, pvStructInfo, *pcbStructInfo);
1433 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1434 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1435 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1436 if (ret && pvStructInfo)
1438 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1439 debugstr_a(algo->pszObjId));
1441 return ret;
1444 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1445 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1446 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1448 BOOL ret = TRUE;
1449 struct AsnDecodeSequenceItem items[] = {
1450 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1451 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1452 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1453 Algorithm.pszObjId) },
1454 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1455 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1456 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1458 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1460 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1461 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1462 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1463 info->Algorithm.Parameters.pbData : NULL);
1464 return ret;
1467 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1468 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1469 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1471 BOOL ret = TRUE;
1473 __TRY
1475 DWORD bytesNeeded;
1477 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1478 lpszStructType, pbEncoded, cbEncoded,
1479 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1481 if (!pvStructInfo)
1482 *pcbStructInfo = bytesNeeded;
1483 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1484 pvStructInfo, pcbStructInfo, bytesNeeded)))
1486 PCERT_PUBLIC_KEY_INFO info;
1488 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1489 pvStructInfo = *(BYTE **)pvStructInfo;
1490 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1491 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
1492 sizeof(CERT_PUBLIC_KEY_INFO);
1493 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1494 lpszStructType, pbEncoded, cbEncoded,
1495 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1496 &bytesNeeded);
1500 __EXCEPT_PAGE_FAULT
1502 SetLastError(STATUS_ACCESS_VIOLATION);
1503 ret = FALSE;
1505 __ENDTRY
1506 return ret;
1509 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
1510 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1511 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1513 BOOL ret;
1515 if (cbEncoded < 3)
1517 SetLastError(CRYPT_E_ASN1_CORRUPT);
1518 return FALSE;
1520 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
1522 SetLastError(CRYPT_E_ASN1_CORRUPT);
1523 return FALSE;
1525 if (pbEncoded[1] > 1)
1527 SetLastError(CRYPT_E_ASN1_CORRUPT);
1528 return FALSE;
1530 if (!pvStructInfo)
1532 *pcbStructInfo = sizeof(BOOL);
1533 ret = TRUE;
1535 else if (*pcbStructInfo < sizeof(BOOL))
1537 *pcbStructInfo = sizeof(BOOL);
1538 SetLastError(ERROR_MORE_DATA);
1539 ret = FALSE;
1541 else
1543 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
1544 ret = TRUE;
1546 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1547 return ret;
1550 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
1551 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1552 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1554 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
1555 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
1556 BOOL ret;
1558 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1559 pDecodePara, pvStructInfo, *pcbStructInfo);
1561 if (cbEncoded < 2)
1563 SetLastError(CRYPT_E_ASN1_CORRUPT);
1564 return FALSE;
1566 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
1568 SetLastError(CRYPT_E_ASN1_BADTAG);
1569 return FALSE;
1571 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1572 if (1 + lenBytes > cbEncoded)
1574 SetLastError(CRYPT_E_ASN1_CORRUPT);
1575 return FALSE;
1577 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1579 switch (pbEncoded[0] & ASN_TYPE_MASK)
1581 case 1: /* rfc822Name */
1582 case 2: /* dNSName */
1583 case 6: /* uniformResourceIdentifier */
1584 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1585 break;
1586 case 7: /* iPAddress */
1587 bytesNeeded += dataLen;
1588 break;
1589 case 8: /* registeredID */
1590 /* FIXME: decode as OID */
1591 case 0: /* otherName */
1592 case 4: /* directoryName */
1593 FIXME("stub\n");
1594 SetLastError(CRYPT_E_ASN1_BADTAG);
1595 ret = FALSE;
1596 break;
1597 case 3: /* x400Address, unimplemented */
1598 case 5: /* ediPartyName, unimplemented */
1599 SetLastError(CRYPT_E_ASN1_BADTAG);
1600 ret = FALSE;
1601 break;
1602 default:
1603 SetLastError(CRYPT_E_ASN1_CORRUPT);
1604 ret = FALSE;
1606 if (ret)
1608 if (!entry)
1609 *pcbStructInfo = bytesNeeded;
1610 else if (*pcbStructInfo < bytesNeeded)
1612 *pcbStructInfo = bytesNeeded;
1613 SetLastError(ERROR_MORE_DATA);
1614 ret = FALSE;
1616 else
1618 *pcbStructInfo = bytesNeeded;
1619 /* MS used values one greater than the asn1 ones.. sigh */
1620 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
1621 switch (pbEncoded[0] & ASN_TYPE_MASK)
1623 case 1: /* rfc822Name */
1624 case 2: /* dNSName */
1625 case 6: /* uniformResourceIdentifier */
1627 DWORD i;
1629 for (i = 0; i < dataLen; i++)
1630 entry->u.pwszURL[i] =
1631 (WCHAR)pbEncoded[1 + lenBytes + i];
1632 entry->u.pwszURL[i] = 0;
1633 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
1634 debugstr_w(entry->u.pwszURL));
1635 break;
1637 case 7: /* iPAddress */
1638 /* The next data pointer is in the pwszURL spot, that is,
1639 * the first 4 bytes. Need to move it to the next spot.
1641 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
1642 entry->u.IPAddress.cbData = dataLen;
1643 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
1644 dataLen);
1645 break;
1650 return ret;
1653 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
1654 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1655 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1657 BOOL ret = TRUE;
1658 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1659 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
1660 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
1661 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
1663 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1664 pDecodePara, pvStructInfo, *pcbStructInfo);
1666 if (info)
1667 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
1668 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1669 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
1670 return ret;
1673 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
1674 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1675 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1677 BOOL ret = TRUE;
1679 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1680 pDecodePara, pvStructInfo, *pcbStructInfo);
1682 __TRY
1684 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1685 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
1686 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
1688 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1689 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1691 __EXCEPT_PAGE_FAULT
1693 SetLastError(STATUS_ACCESS_VIOLATION);
1694 ret = FALSE;
1696 __ENDTRY
1697 return ret;
1700 struct PATH_LEN_CONSTRAINT
1702 BOOL fPathLenConstraint;
1703 DWORD dwPathLenConstraint;
1706 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
1707 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1708 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1710 BOOL ret = TRUE;
1712 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1713 pvStructInfo, *pcbStructInfo);
1715 if (cbEncoded)
1717 if (pbEncoded[0] == ASN_INTEGER)
1719 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
1721 if (!pvStructInfo)
1722 *pcbStructInfo = bytesNeeded;
1723 else if (*pcbStructInfo < bytesNeeded)
1725 SetLastError(ERROR_MORE_DATA);
1726 *pcbStructInfo = bytesNeeded;
1727 ret = FALSE;
1729 else
1731 struct PATH_LEN_CONSTRAINT *constraint =
1732 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
1733 DWORD size = sizeof(constraint->dwPathLenConstraint);
1735 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
1736 pbEncoded, cbEncoded, 0, NULL,
1737 &constraint->dwPathLenConstraint, &size);
1738 if (ret)
1739 constraint->fPathLenConstraint = TRUE;
1740 TRACE("got an int, dwPathLenConstraint is %ld\n",
1741 constraint->dwPathLenConstraint);
1744 else
1746 SetLastError(CRYPT_E_ASN1_CORRUPT);
1747 ret = FALSE;
1750 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1751 return ret;
1754 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
1755 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1756 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1758 BOOL ret;
1759 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1760 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
1761 offsetof(CERT_NAME_BLOB, pbData) };
1762 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1764 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1765 pDecodePara, pvStructInfo, *pcbStructInfo);
1767 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1768 pDecodePara, pvStructInfo, pcbStructInfo,
1769 entries ? entries->rgItems : NULL);
1770 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1771 return ret;
1774 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
1775 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1776 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1778 BOOL ret;
1780 __TRY
1782 struct AsnDecodeSequenceItem items[] = {
1783 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
1784 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1785 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
1786 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
1787 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
1788 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
1789 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
1790 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
1791 sizeof(struct GenericArray), TRUE, TRUE,
1792 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
1795 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1796 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1797 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1799 __EXCEPT_PAGE_FAULT
1801 SetLastError(STATUS_ACCESS_VIOLATION);
1802 ret = FALSE;
1804 __ENDTRY
1805 return ret;
1808 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
1809 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1810 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1812 BOOL ret;
1814 __TRY
1816 struct AsnDecodeSequenceItem items[] = {
1817 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
1818 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
1819 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
1820 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
1821 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
1824 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1825 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1826 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1828 __EXCEPT_PAGE_FAULT
1830 SetLastError(STATUS_ACCESS_VIOLATION);
1831 ret = FALSE;
1833 __ENDTRY
1834 return ret;
1837 #define RSA1_MAGIC 0x31415352
1839 struct DECODED_RSA_PUB_KEY
1841 DWORD pubexp;
1842 CRYPT_INTEGER_BLOB modulus;
1845 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
1846 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1847 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1849 BOOL ret;
1851 __TRY
1853 struct AsnDecodeSequenceItem items[] = {
1854 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
1855 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
1856 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
1857 0 },
1858 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
1859 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
1861 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
1862 DWORD size = 0;
1864 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1865 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
1866 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
1867 if (ret)
1869 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1870 decodedKey->modulus.cbData;
1872 if (!pvStructInfo)
1874 *pcbStructInfo = bytesNeeded;
1875 ret = TRUE;
1877 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1878 pvStructInfo, pcbStructInfo, bytesNeeded)))
1880 BLOBHEADER *hdr;
1881 RSAPUBKEY *rsaPubKey;
1883 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1884 pvStructInfo = *(BYTE **)pvStructInfo;
1885 hdr = (BLOBHEADER *)pvStructInfo;
1886 hdr->bType = PUBLICKEYBLOB;
1887 hdr->bVersion = CUR_BLOB_VERSION;
1888 hdr->reserved = 0;
1889 hdr->aiKeyAlg = CALG_RSA_KEYX;
1890 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
1891 sizeof(BLOBHEADER));
1892 rsaPubKey->magic = RSA1_MAGIC;
1893 rsaPubKey->pubexp = decodedKey->pubexp;
1894 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
1895 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
1896 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
1897 decodedKey->modulus.cbData);
1899 LocalFree(decodedKey);
1902 __EXCEPT_PAGE_FAULT
1904 SetLastError(STATUS_ACCESS_VIOLATION);
1905 ret = FALSE;
1907 __ENDTRY
1908 return ret;
1911 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
1912 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1913 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1915 BOOL ret;
1916 DWORD bytesNeeded, dataLen;
1918 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1919 pDecodePara, pvStructInfo, *pcbStructInfo);
1921 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1923 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1924 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
1925 else
1926 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
1927 if (!pvStructInfo)
1928 *pcbStructInfo = bytesNeeded;
1929 else if (*pcbStructInfo < bytesNeeded)
1931 SetLastError(ERROR_MORE_DATA);
1932 *pcbStructInfo = bytesNeeded;
1933 ret = FALSE;
1935 else
1937 CRYPT_DATA_BLOB *blob;
1938 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1940 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
1941 blob->cbData = dataLen;
1942 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1943 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
1944 else
1946 assert(blob->pbData);
1947 if (blob->cbData)
1948 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
1949 blob->cbData);
1953 return ret;
1956 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
1957 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1958 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1960 BOOL ret;
1962 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1963 pDecodePara, pvStructInfo, *pcbStructInfo);
1965 __TRY
1967 DWORD bytesNeeded;
1969 if (!cbEncoded)
1971 SetLastError(CRYPT_E_ASN1_CORRUPT);
1972 ret = FALSE;
1974 else if (pbEncoded[0] != ASN_OCTETSTRING)
1976 SetLastError(CRYPT_E_ASN1_BADTAG);
1977 ret = FALSE;
1979 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
1980 lpszStructType, pbEncoded, cbEncoded,
1981 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1983 if (!pvStructInfo)
1984 *pcbStructInfo = bytesNeeded;
1985 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1986 pvStructInfo, pcbStructInfo, bytesNeeded)))
1988 CRYPT_DATA_BLOB *blob;
1990 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1991 pvStructInfo = *(BYTE **)pvStructInfo;
1992 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
1993 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
1994 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
1995 lpszStructType, pbEncoded, cbEncoded,
1996 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1997 &bytesNeeded);
2001 __EXCEPT_PAGE_FAULT
2003 SetLastError(STATUS_ACCESS_VIOLATION);
2004 ret = FALSE;
2006 __ENDTRY
2007 return ret;
2010 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2011 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2012 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2014 BOOL ret;
2016 TRACE("(%p, %ld, 0x%08lx, %p, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2017 pDecodePara, pvStructInfo, *pcbStructInfo);
2019 if (pbEncoded[0] == ASN_BITSTRING)
2021 DWORD bytesNeeded, dataLen;
2023 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2025 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2026 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2027 else
2028 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2029 if (!pvStructInfo)
2030 *pcbStructInfo = bytesNeeded;
2031 else if (*pcbStructInfo < bytesNeeded)
2033 *pcbStructInfo = bytesNeeded;
2034 SetLastError(ERROR_MORE_DATA);
2035 ret = FALSE;
2037 else
2039 CRYPT_BIT_BLOB *blob;
2041 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2042 blob->cbData = dataLen - 1;
2043 blob->cUnusedBits = *(pbEncoded + 1 +
2044 GET_LEN_BYTES(pbEncoded[1]));
2045 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2047 blob->pbData = (BYTE *)pbEncoded + 2 +
2048 GET_LEN_BYTES(pbEncoded[1]);
2050 else
2052 assert(blob->pbData);
2053 if (blob->cbData)
2055 BYTE mask = 0xff << blob->cUnusedBits;
2057 memcpy(blob->pbData, pbEncoded + 2 +
2058 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2059 blob->pbData[blob->cbData - 1] &= mask;
2065 else
2067 SetLastError(CRYPT_E_ASN1_BADTAG);
2068 ret = FALSE;
2070 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2071 return ret;
2074 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2075 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2076 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2078 BOOL ret;
2080 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2081 pDecodePara, pvStructInfo, pcbStructInfo);
2083 __TRY
2085 DWORD bytesNeeded;
2087 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2088 lpszStructType, pbEncoded, cbEncoded,
2089 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2091 if (!pvStructInfo)
2092 *pcbStructInfo = bytesNeeded;
2093 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2094 pvStructInfo, pcbStructInfo, bytesNeeded)))
2096 CRYPT_BIT_BLOB *blob;
2098 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2099 pvStructInfo = *(BYTE **)pvStructInfo;
2100 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2101 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2102 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2103 lpszStructType, pbEncoded, cbEncoded,
2104 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2105 &bytesNeeded);
2109 __EXCEPT_PAGE_FAULT
2111 SetLastError(STATUS_ACCESS_VIOLATION);
2112 ret = FALSE;
2114 __ENDTRY
2115 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2116 return ret;
2119 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2120 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2121 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2123 BOOL ret;
2125 if (!pvStructInfo)
2127 *pcbStructInfo = sizeof(int);
2128 return TRUE;
2130 __TRY
2132 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2133 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2134 DWORD size = sizeof(buf);
2136 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2137 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2138 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf, &size);
2139 if (ret)
2141 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2142 pvStructInfo, pcbStructInfo, sizeof(int))))
2144 int val, i;
2146 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2147 pvStructInfo = *(BYTE **)pvStructInfo;
2148 if (blob->pbData[blob->cbData - 1] & 0x80)
2150 /* initialize to a negative value to sign-extend */
2151 val = -1;
2153 else
2154 val = 0;
2155 for (i = 0; i < blob->cbData; i++)
2157 val <<= 8;
2158 val |= blob->pbData[blob->cbData - i - 1];
2160 memcpy(pvStructInfo, &val, sizeof(int));
2163 else if (GetLastError() == ERROR_MORE_DATA)
2164 SetLastError(CRYPT_E_ASN1_LARGE);
2166 __EXCEPT_PAGE_FAULT
2168 SetLastError(STATUS_ACCESS_VIOLATION);
2169 ret = FALSE;
2171 __ENDTRY
2172 return ret;
2175 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2176 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2177 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2179 BOOL ret;
2181 if (pbEncoded[0] == ASN_INTEGER)
2183 DWORD bytesNeeded, dataLen;
2185 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2187 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2189 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2190 if (!pvStructInfo)
2191 *pcbStructInfo = bytesNeeded;
2192 else if (*pcbStructInfo < bytesNeeded)
2194 *pcbStructInfo = bytesNeeded;
2195 SetLastError(ERROR_MORE_DATA);
2196 ret = FALSE;
2198 else
2200 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2202 blob->cbData = dataLen;
2203 assert(blob->pbData);
2204 if (blob->cbData)
2206 DWORD i;
2208 for (i = 0; i < blob->cbData; i++)
2210 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2211 dataLen - i - 1);
2217 else
2219 SetLastError(CRYPT_E_ASN1_BADTAG);
2220 ret = FALSE;
2222 return ret;
2225 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2226 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2227 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2229 BOOL ret;
2231 __TRY
2233 DWORD bytesNeeded;
2235 if ((ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2236 lpszStructType, pbEncoded, cbEncoded,
2237 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2239 if (!pvStructInfo)
2240 *pcbStructInfo = bytesNeeded;
2241 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2242 pvStructInfo, pcbStructInfo, bytesNeeded)))
2244 CRYPT_INTEGER_BLOB *blob;
2246 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2247 pvStructInfo = *(BYTE **)pvStructInfo;
2248 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2249 blob->pbData = (BYTE *)pvStructInfo +
2250 sizeof(CRYPT_INTEGER_BLOB);
2251 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2252 lpszStructType, pbEncoded, cbEncoded,
2253 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2254 &bytesNeeded);
2258 __EXCEPT_PAGE_FAULT
2260 SetLastError(STATUS_ACCESS_VIOLATION);
2261 ret = FALSE;
2263 __ENDTRY
2264 return ret;
2267 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
2268 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2269 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2270 void *pvStructInfo, DWORD *pcbStructInfo)
2272 BOOL ret;
2274 if (pbEncoded[0] == ASN_INTEGER)
2276 DWORD bytesNeeded, dataLen;
2278 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2280 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2282 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2283 if (!pvStructInfo)
2284 *pcbStructInfo = bytesNeeded;
2285 else if (*pcbStructInfo < bytesNeeded)
2287 *pcbStructInfo = bytesNeeded;
2288 SetLastError(ERROR_MORE_DATA);
2289 ret = FALSE;
2291 else
2293 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2295 blob->cbData = dataLen;
2296 assert(blob->pbData);
2297 /* remove leading zero byte if it exists */
2298 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2300 blob->cbData--;
2301 blob->pbData++;
2303 if (blob->cbData)
2305 DWORD i;
2307 for (i = 0; i < blob->cbData; i++)
2309 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2310 dataLen - i - 1);
2316 else
2318 SetLastError(CRYPT_E_ASN1_BADTAG);
2319 ret = FALSE;
2321 return ret;
2324 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2325 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2326 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2328 BOOL ret;
2330 __TRY
2332 DWORD bytesNeeded;
2334 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2335 lpszStructType, pbEncoded, cbEncoded,
2336 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2338 if (!pvStructInfo)
2339 *pcbStructInfo = bytesNeeded;
2340 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2341 pvStructInfo, pcbStructInfo, bytesNeeded)))
2343 CRYPT_INTEGER_BLOB *blob;
2345 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2346 pvStructInfo = *(BYTE **)pvStructInfo;
2347 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2348 blob->pbData = (BYTE *)pvStructInfo +
2349 sizeof(CRYPT_INTEGER_BLOB);
2350 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2351 lpszStructType, pbEncoded, cbEncoded,
2352 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2353 &bytesNeeded);
2357 __EXCEPT_PAGE_FAULT
2359 SetLastError(STATUS_ACCESS_VIOLATION);
2360 ret = FALSE;
2362 __ENDTRY
2363 return ret;
2366 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
2367 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2368 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2370 BOOL ret;
2372 if (!pvStructInfo)
2374 *pcbStructInfo = sizeof(int);
2375 return TRUE;
2377 __TRY
2379 if (pbEncoded[0] == ASN_ENUMERATED)
2381 unsigned int val = 0, i;
2383 if (cbEncoded <= 1)
2385 SetLastError(CRYPT_E_ASN1_EOD);
2386 ret = FALSE;
2388 else if (pbEncoded[1] == 0)
2390 SetLastError(CRYPT_E_ASN1_CORRUPT);
2391 ret = FALSE;
2393 else
2395 /* A little strange looking, but we have to accept a sign byte:
2396 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
2397 * assuming a small length is okay here, it has to be in short
2398 * form.
2400 if (pbEncoded[1] > sizeof(unsigned int) + 1)
2402 SetLastError(CRYPT_E_ASN1_LARGE);
2403 return FALSE;
2405 for (i = 0; i < pbEncoded[1]; i++)
2407 val <<= 8;
2408 val |= pbEncoded[2 + i];
2410 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2411 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
2413 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2414 pvStructInfo = *(BYTE **)pvStructInfo;
2415 memcpy(pvStructInfo, &val, sizeof(unsigned int));
2419 else
2421 SetLastError(CRYPT_E_ASN1_BADTAG);
2422 ret = FALSE;
2425 __EXCEPT_PAGE_FAULT
2427 SetLastError(STATUS_ACCESS_VIOLATION);
2428 ret = FALSE;
2430 __ENDTRY
2431 return ret;
2434 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
2435 * if it fails.
2437 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
2438 do { \
2439 BYTE i; \
2441 (word) = 0; \
2442 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
2444 if (!isdigit(*(pbEncoded))) \
2446 SetLastError(CRYPT_E_ASN1_CORRUPT); \
2447 ret = FALSE; \
2449 else \
2451 (word) *= 10; \
2452 (word) += *(pbEncoded)++ - '0'; \
2455 } while (0)
2457 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
2458 SYSTEMTIME *sysTime)
2460 BOOL ret;
2462 __TRY
2464 ret = TRUE;
2465 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
2467 WORD hours, minutes = 0;
2468 BYTE sign = *pbEncoded++;
2470 len--;
2471 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
2472 if (ret && hours >= 24)
2474 SetLastError(CRYPT_E_ASN1_CORRUPT);
2475 ret = FALSE;
2477 else if (len >= 2)
2479 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
2480 if (ret && minutes >= 60)
2482 SetLastError(CRYPT_E_ASN1_CORRUPT);
2483 ret = FALSE;
2486 if (ret)
2488 if (sign == '+')
2490 sysTime->wHour += hours;
2491 sysTime->wMinute += minutes;
2493 else
2495 if (hours > sysTime->wHour)
2497 sysTime->wDay--;
2498 sysTime->wHour = 24 - (hours - sysTime->wHour);
2500 else
2501 sysTime->wHour -= hours;
2502 if (minutes > sysTime->wMinute)
2504 sysTime->wHour--;
2505 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
2507 else
2508 sysTime->wMinute -= minutes;
2513 __EXCEPT_PAGE_FAULT
2515 SetLastError(STATUS_ACCESS_VIOLATION);
2516 ret = FALSE;
2518 __ENDTRY
2519 return ret;
2522 #define MIN_ENCODED_TIME_LENGTH 10
2524 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
2525 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2526 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2528 BOOL ret;
2530 if (!pvStructInfo)
2532 *pcbStructInfo = sizeof(FILETIME);
2533 return TRUE;
2535 __TRY
2537 ret = TRUE;
2538 if (pbEncoded[0] == ASN_UTCTIME)
2540 if (cbEncoded <= 1)
2542 SetLastError(CRYPT_E_ASN1_EOD);
2543 ret = FALSE;
2545 else if (pbEncoded[1] > 0x7f)
2547 /* long-form date strings really can't be valid */
2548 SetLastError(CRYPT_E_ASN1_CORRUPT);
2549 ret = FALSE;
2551 else
2553 SYSTEMTIME sysTime = { 0 };
2554 BYTE len = pbEncoded[1];
2556 if (len < MIN_ENCODED_TIME_LENGTH)
2558 SetLastError(CRYPT_E_ASN1_CORRUPT);
2559 ret = FALSE;
2561 else
2563 pbEncoded += 2;
2564 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
2565 if (sysTime.wYear >= 50)
2566 sysTime.wYear += 1900;
2567 else
2568 sysTime.wYear += 2000;
2569 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2570 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2571 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2572 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
2573 if (ret && len > 0)
2575 if (len >= 2 && isdigit(*pbEncoded) &&
2576 isdigit(*(pbEncoded + 1)))
2577 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2578 sysTime.wSecond);
2579 else if (isdigit(*pbEncoded))
2580 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
2581 sysTime.wSecond);
2582 if (ret)
2583 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2584 &sysTime);
2586 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2587 pDecodePara, pvStructInfo, pcbStructInfo,
2588 sizeof(FILETIME))))
2590 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2591 pvStructInfo = *(BYTE **)pvStructInfo;
2592 ret = SystemTimeToFileTime(&sysTime,
2593 (FILETIME *)pvStructInfo);
2598 else
2600 SetLastError(CRYPT_E_ASN1_BADTAG);
2601 ret = FALSE;
2604 __EXCEPT_PAGE_FAULT
2606 SetLastError(STATUS_ACCESS_VIOLATION);
2607 ret = FALSE;
2609 __ENDTRY
2610 return ret;
2613 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
2614 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2615 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2617 BOOL ret;
2619 if (!pvStructInfo)
2621 *pcbStructInfo = sizeof(FILETIME);
2622 return TRUE;
2624 __TRY
2626 ret = TRUE;
2627 if (pbEncoded[0] == ASN_GENERALTIME)
2629 if (cbEncoded <= 1)
2631 SetLastError(CRYPT_E_ASN1_EOD);
2632 ret = FALSE;
2634 else if (pbEncoded[1] > 0x7f)
2636 /* long-form date strings really can't be valid */
2637 SetLastError(CRYPT_E_ASN1_CORRUPT);
2638 ret = FALSE;
2640 else
2642 BYTE len = pbEncoded[1];
2644 if (len < MIN_ENCODED_TIME_LENGTH)
2646 SetLastError(CRYPT_E_ASN1_CORRUPT);
2647 ret = FALSE;
2649 else
2651 SYSTEMTIME sysTime = { 0 };
2653 pbEncoded += 2;
2654 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
2655 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2656 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2657 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2658 if (ret && len > 0)
2660 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2661 sysTime.wMinute);
2662 if (ret && len > 0)
2663 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
2664 sysTime.wSecond);
2665 if (ret && len > 0 && (*pbEncoded == '.' ||
2666 *pbEncoded == ','))
2668 BYTE digits;
2670 pbEncoded++;
2671 len--;
2672 /* workaround macro weirdness */
2673 digits = min(len, 3);
2674 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
2675 sysTime.wMilliseconds);
2677 if (ret)
2678 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
2679 &sysTime);
2681 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
2682 pDecodePara, pvStructInfo, pcbStructInfo,
2683 sizeof(FILETIME))))
2685 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2686 pvStructInfo = *(BYTE **)pvStructInfo;
2687 ret = SystemTimeToFileTime(&sysTime,
2688 (FILETIME *)pvStructInfo);
2693 else
2695 SetLastError(CRYPT_E_ASN1_BADTAG);
2696 ret = FALSE;
2699 __EXCEPT_PAGE_FAULT
2701 SetLastError(STATUS_ACCESS_VIOLATION);
2702 ret = FALSE;
2704 __ENDTRY
2705 return ret;
2708 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
2709 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2710 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2712 BOOL ret;
2714 __TRY
2716 if (pbEncoded[0] == ASN_UTCTIME)
2717 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
2718 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2719 pcbStructInfo);
2720 else if (pbEncoded[0] == ASN_GENERALTIME)
2721 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
2722 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
2723 pvStructInfo, pcbStructInfo);
2724 else
2726 SetLastError(CRYPT_E_ASN1_BADTAG);
2727 ret = FALSE;
2730 __EXCEPT_PAGE_FAULT
2732 SetLastError(STATUS_ACCESS_VIOLATION);
2733 ret = FALSE;
2735 __ENDTRY
2736 return ret;
2739 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
2740 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2741 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2743 BOOL ret = TRUE;
2745 __TRY
2747 if (pbEncoded[0] == ASN_SEQUENCEOF)
2749 DWORD bytesNeeded, dataLen, remainingLen, cValue;
2751 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2753 BYTE lenBytes;
2754 const BYTE *ptr;
2756 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2757 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
2758 cValue = 0;
2759 ptr = pbEncoded + 1 + lenBytes;
2760 remainingLen = dataLen;
2761 while (ret && remainingLen)
2763 DWORD nextLen;
2765 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
2766 if (ret)
2768 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
2770 remainingLen -= 1 + nextLenBytes + nextLen;
2771 ptr += 1 + nextLenBytes + nextLen;
2772 bytesNeeded += sizeof(CRYPT_DER_BLOB);
2773 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2774 bytesNeeded += 1 + nextLenBytes + nextLen;
2775 cValue++;
2778 if (ret)
2780 CRYPT_SEQUENCE_OF_ANY *seq;
2781 BYTE *nextPtr;
2782 DWORD i;
2784 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2785 pvStructInfo, pcbStructInfo, bytesNeeded)))
2787 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2788 pvStructInfo = *(BYTE **)pvStructInfo;
2789 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
2790 seq->cValue = cValue;
2791 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
2792 sizeof(*seq));
2793 nextPtr = (BYTE *)seq->rgValue +
2794 cValue * sizeof(CRYPT_DER_BLOB);
2795 ptr = pbEncoded + 1 + lenBytes;
2796 remainingLen = dataLen;
2797 i = 0;
2798 while (ret && remainingLen)
2800 DWORD nextLen;
2802 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
2803 if (ret)
2805 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
2807 seq->rgValue[i].cbData = 1 + nextLenBytes +
2808 nextLen;
2809 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2810 seq->rgValue[i].pbData = (BYTE *)ptr;
2811 else
2813 seq->rgValue[i].pbData = nextPtr;
2814 memcpy(nextPtr, ptr, 1 + nextLenBytes +
2815 nextLen);
2816 nextPtr += 1 + nextLenBytes + nextLen;
2818 remainingLen -= 1 + nextLenBytes + nextLen;
2819 ptr += 1 + nextLenBytes + nextLen;
2820 i++;
2827 else
2829 SetLastError(CRYPT_E_ASN1_BADTAG);
2830 return FALSE;
2833 __EXCEPT_PAGE_FAULT
2835 SetLastError(STATUS_ACCESS_VIOLATION);
2836 ret = FALSE;
2838 __ENDTRY
2839 return ret;
2842 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
2843 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2844 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2846 struct AsnDecodeSequenceItem items[] = {
2847 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
2848 DistPointName), CRYPT_AsnDecodeAltNameInternal,
2849 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
2850 DistPointName.u.FullName.rgAltEntry), 0 },
2851 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
2852 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
2853 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
2854 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
2855 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
2856 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
2858 BOOL ret;
2860 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2861 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2862 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2863 return ret;
2866 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
2867 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2868 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2870 BOOL ret;
2872 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2873 pDecodePara, pvStructInfo, *pcbStructInfo);
2875 __TRY
2877 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2878 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
2879 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
2881 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2882 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2884 __EXCEPT_PAGE_FAULT
2886 SetLastError(STATUS_ACCESS_VIOLATION);
2887 ret = FALSE;
2889 __ENDTRY
2890 return ret;
2893 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
2894 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2895 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2897 BOOL ret;
2899 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2900 pDecodePara, pvStructInfo, *pcbStructInfo);
2902 __TRY
2904 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2905 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2907 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2908 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2910 __EXCEPT_PAGE_FAULT
2912 SetLastError(STATUS_ACCESS_VIOLATION);
2913 ret = FALSE;
2915 __ENDTRY
2916 return ret;
2919 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
2920 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2921 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2923 static HCRYPTOIDFUNCSET set = NULL;
2924 BOOL ret = FALSE;
2925 CryptDecodeObjectExFunc decodeFunc = NULL;
2926 HCRYPTOIDFUNCADDR hFunc = NULL;
2928 TRACE("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
2929 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
2930 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
2932 if (!pvStructInfo && !pcbStructInfo)
2934 SetLastError(ERROR_INVALID_PARAMETER);
2935 return FALSE;
2937 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
2938 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
2940 SetLastError(ERROR_FILE_NOT_FOUND);
2941 return FALSE;
2943 if (!cbEncoded)
2945 SetLastError(CRYPT_E_ASN1_EOD);
2946 return FALSE;
2948 if (cbEncoded > MAX_ENCODED_LEN)
2950 SetLastError(CRYPT_E_ASN1_LARGE);
2951 return FALSE;
2954 SetLastError(NOERROR);
2955 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
2956 *(BYTE **)pvStructInfo = NULL;
2957 if (!HIWORD(lpszStructType))
2959 switch (LOWORD(lpszStructType))
2961 case (WORD)X509_CERT:
2962 decodeFunc = CRYPT_AsnDecodeCert;
2963 break;
2964 case (WORD)X509_CERT_TO_BE_SIGNED:
2965 decodeFunc = CRYPT_AsnDecodeCertInfo;
2966 break;
2967 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
2968 decodeFunc = CRYPT_AsnDecodeCRLInfo;
2969 break;
2970 case (WORD)X509_EXTENSIONS:
2971 decodeFunc = CRYPT_AsnDecodeExtensions;
2972 break;
2973 case (WORD)X509_NAME:
2974 decodeFunc = CRYPT_AsnDecodeName;
2975 break;
2976 case (WORD)X509_PUBLIC_KEY_INFO:
2977 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
2978 break;
2979 case (WORD)X509_ALTERNATE_NAME:
2980 decodeFunc = CRYPT_AsnDecodeAltName;
2981 break;
2982 case (WORD)X509_BASIC_CONSTRAINTS:
2983 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
2984 break;
2985 case (WORD)X509_BASIC_CONSTRAINTS2:
2986 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
2987 break;
2988 case (WORD)RSA_CSP_PUBLICKEYBLOB:
2989 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
2990 break;
2991 case (WORD)X509_OCTET_STRING:
2992 decodeFunc = CRYPT_AsnDecodeOctets;
2993 break;
2994 case (WORD)X509_BITS:
2995 case (WORD)X509_KEY_USAGE:
2996 decodeFunc = CRYPT_AsnDecodeBits;
2997 break;
2998 case (WORD)X509_INTEGER:
2999 decodeFunc = CRYPT_AsnDecodeInt;
3000 break;
3001 case (WORD)X509_MULTI_BYTE_INTEGER:
3002 decodeFunc = CRYPT_AsnDecodeInteger;
3003 break;
3004 case (WORD)X509_MULTI_BYTE_UINT:
3005 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3006 break;
3007 case (WORD)X509_ENUMERATED:
3008 decodeFunc = CRYPT_AsnDecodeEnumerated;
3009 break;
3010 case (WORD)X509_CHOICE_OF_TIME:
3011 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3012 break;
3013 case (WORD)X509_SEQUENCE_OF_ANY:
3014 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3015 break;
3016 case (WORD)PKCS_UTC_TIME:
3017 decodeFunc = CRYPT_AsnDecodeUtcTime;
3018 break;
3019 case (WORD)X509_CRL_DIST_POINTS:
3020 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3021 break;
3022 case (WORD)X509_ENHANCED_KEY_USAGE:
3023 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3024 break;
3025 default:
3026 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3029 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3030 decodeFunc = CRYPT_AsnDecodeExtensions;
3031 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3032 decodeFunc = CRYPT_AsnDecodeUtcTime;
3033 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3034 decodeFunc = CRYPT_AsnDecodeEnumerated;
3035 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3036 decodeFunc = CRYPT_AsnDecodeBits;
3037 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3038 decodeFunc = CRYPT_AsnDecodeOctets;
3039 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3040 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3041 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3042 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3043 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3044 decodeFunc = CRYPT_AsnDecodeAltName;
3045 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3046 decodeFunc = CRYPT_AsnDecodeAltName;
3047 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3048 decodeFunc = CRYPT_AsnDecodeAltName;
3049 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3050 decodeFunc = CRYPT_AsnDecodeAltName;
3051 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3052 decodeFunc = CRYPT_AsnDecodeAltName;
3053 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3054 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3055 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3056 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3057 else
3058 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3059 debugstr_a(lpszStructType));
3060 if (!decodeFunc)
3062 if (!set)
3063 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
3064 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3065 (void **)&decodeFunc, &hFunc);
3067 if (decodeFunc)
3068 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3069 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3070 else
3071 SetLastError(ERROR_FILE_NOT_FOUND);
3072 if (hFunc)
3073 CryptFreeOIDFunctionAddress(hFunc, 0);
3074 return ret;