crypt32: Fix a bad comment.
[wine/wine-kai.git] / dlls / crypt32 / decode.c
blob29687ef3857a9fb83c02f8dc7f95b729ab2b768e
1 /*
2 * Copyright 2005 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface is
21 * undocumented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially:
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
34 #include <assert.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
39 #define NONAMELESSUNION
41 #include "windef.h"
42 #include "winbase.h"
43 #include "wincrypt.h"
44 #include "winnls.h"
45 #include "snmp.h"
46 #include "wine/debug.h"
47 #include "wine/exception.h"
48 #include "crypt32_private.h"
50 /* This is a bit arbitrary, but to set some limit: */
51 #define MAX_ENCODED_LEN 0x02000000
53 #define ASN_FLAGS_MASK 0xe0
54 #define ASN_TYPE_MASK 0x1f
56 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
58 struct GenericArray
60 DWORD cItems;
61 BYTE *rgItems;
64 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
65 DWORD, DWORD, void *, DWORD *);
66 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
67 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
69 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
70 * The dwCertEncodingType and lpszStructType are ignored by the built-in
71 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
72 * since it must call functions in external DLLs that follow these signatures.
74 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
75 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
76 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
77 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
78 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
79 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
80 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
81 * time, doesn't do memory allocation, and doesn't do exception handling.
82 * (This isn't intended to be the externally-called one.)
84 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
85 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
86 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
87 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
88 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
89 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
90 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
91 /* Internal function */
92 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
93 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
94 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
97 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
98 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
99 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
100 * member has been initialized, doesn't do exception handling, and doesn't do
101 * memory allocation.
103 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
104 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
105 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
106 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
107 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
108 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
109 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
110 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
111 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
112 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
113 * member has been initialized, doesn't do exception handling, and doesn't do
114 * memory allocation. Also doesn't check tag, assumes the caller has checked
115 * it.
117 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
118 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
119 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
120 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
121 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
122 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
123 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
124 void *pvStructInfo, DWORD *pcbStructInfo);
126 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
127 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
128 DWORD *pcbStructInfo)
130 static HCRYPTOIDFUNCSET set = NULL;
131 BOOL ret = FALSE;
132 CryptDecodeObjectFunc pCryptDecodeObject;
133 HCRYPTOIDFUNCADDR hFunc;
135 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
136 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
137 pvStructInfo, pcbStructInfo);
139 if (!pvStructInfo && !pcbStructInfo)
141 SetLastError(ERROR_INVALID_PARAMETER);
142 return FALSE;
145 /* Try registered DLL first.. */
146 if (!set)
147 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
148 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
149 (void **)&pCryptDecodeObject, &hFunc);
150 if (pCryptDecodeObject)
152 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
153 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
154 CryptFreeOIDFunctionAddress(hFunc, 0);
156 else
158 /* If not, use CryptDecodeObjectEx */
159 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
160 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
162 return ret;
165 /* Gets the number of length bytes from the given (leading) length byte */
166 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
168 /* Helper function to get the encoded length of the data starting at pbEncoded,
169 * where pbEncoded[0] is the tag. If the data are too short to contain a
170 * length or if the length is too large for cbEncoded, sets an appropriate
171 * error code and returns FALSE.
173 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
174 DWORD *len)
176 BOOL ret;
178 if (cbEncoded <= 1)
180 SetLastError(CRYPT_E_ASN1_CORRUPT);
181 ret = FALSE;
183 else if (pbEncoded[1] <= 0x7f)
185 if (pbEncoded[1] + 1 > cbEncoded)
187 SetLastError(CRYPT_E_ASN1_EOD);
188 ret = FALSE;
190 else
192 *len = pbEncoded[1];
193 ret = TRUE;
196 else
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:
282 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
283 * the offset within the 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 /* Decodes the items in a sequence, where the items are described in items,
301 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
302 * pvStructInfo. nextData is a pointer to the memory location at which the
303 * first decoded item with a dynamic pointer should point.
304 * Upon decoding, *cbDecoded is the total number of bytes decoded.
306 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
307 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
308 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
309 DWORD *cbDecoded)
311 BOOL ret;
312 DWORD i, decoded = 0;
313 const BYTE *ptr = pbEncoded;
315 for (i = 0, ret = TRUE; ret && i < cItem; i++)
317 if (cbEncoded - (ptr - pbEncoded) != 0)
319 DWORD nextItemLen;
321 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
322 &nextItemLen)))
324 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
326 if (ptr[0] == items[i].tag || !items[i].tag)
328 if (nextData && pvStructInfo && items[i].hasPointer)
330 TRACE("Setting next pointer to %p\n",
331 nextData);
332 *(BYTE **)((BYTE *)pvStructInfo +
333 items[i].pointerOffset) = nextData;
335 if (items[i].decodeFunc)
337 if (pvStructInfo)
338 TRACE("decoding item %d\n", i);
339 else
340 TRACE("sizing item %d\n", i);
341 ret = items[i].decodeFunc(dwCertEncodingType,
342 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
343 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
344 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
345 : NULL, &items[i].size);
346 if (ret)
348 if (nextData && items[i].hasPointer &&
349 items[i].size > items[i].minSize)
351 nextData += items[i].size - items[i].minSize;
352 /* align nextData to DWORD boundaries */
353 if (items[i].size % sizeof(DWORD))
354 nextData += sizeof(DWORD) - items[i].size %
355 sizeof(DWORD);
357 /* Account for alignment padding */
358 if (items[i].size % sizeof(DWORD))
359 items[i].size += sizeof(DWORD) -
360 items[i].size % sizeof(DWORD);
361 ptr += 1 + nextItemLenBytes + nextItemLen;
362 decoded += 1 + nextItemLenBytes + nextItemLen;
364 else if (items[i].optional &&
365 GetLastError() == CRYPT_E_ASN1_BADTAG)
367 TRACE("skipping optional item %d\n", i);
368 items[i].size = items[i].minSize;
369 SetLastError(NOERROR);
370 ret = TRUE;
372 else
373 TRACE("item %d failed: %08x\n", i,
374 GetLastError());
376 else
378 decoded += 1 + nextItemLenBytes + nextItemLen;
379 items[i].size = items[i].minSize;
382 else if (items[i].optional)
384 TRACE("skipping optional item %d\n", i);
385 items[i].size = items[i].minSize;
387 else
389 TRACE("tag %02x doesn't match expected %02x\n",
390 ptr[0], items[i].tag);
391 SetLastError(CRYPT_E_ASN1_BADTAG);
392 ret = FALSE;
396 else if (items[i].optional)
398 TRACE("missing optional item %d, skipping\n", i);
399 items[i].size = items[i].minSize;
401 else
403 TRACE("not enough bytes for item %d, failing\n", i);
404 SetLastError(CRYPT_E_ASN1_CORRUPT);
405 ret = FALSE;
408 if (ret)
409 *cbDecoded = decoded;
410 return ret;
413 /* This decodes an arbitrary sequence into a contiguous block of memory
414 * (basically, a struct.) Each element being decoded is described by a struct
415 * AsnDecodeSequenceItem, see above.
416 * startingPointer is an optional pointer to the first place where dynamic
417 * data will be stored. If you know the starting offset, you may pass it
418 * here. Otherwise, pass NULL, and one will be inferred from the items.
419 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
421 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
422 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
423 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
424 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
426 BOOL ret;
428 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
429 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
430 startingPointer);
432 if (pbEncoded[0] == ASN_SEQUENCE)
434 DWORD dataLen;
436 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
438 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
439 const BYTE *ptr = pbEncoded + 1 + lenBytes;
441 cbEncoded -= 1 + lenBytes;
442 if (cbEncoded < dataLen)
444 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
445 cbEncoded);
446 SetLastError(CRYPT_E_ASN1_CORRUPT);
447 ret = FALSE;
449 else
450 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
451 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
452 if (ret && cbDecoded != dataLen)
454 TRACE("expected %d decoded, got %d, failing\n", dataLen,
455 cbDecoded);
456 SetLastError(CRYPT_E_ASN1_CORRUPT);
457 ret = FALSE;
459 if (ret)
461 DWORD i, bytesNeeded = 0, structSize = 0;
463 for (i = 0; i < cItem; i++)
465 bytesNeeded += items[i].size;
466 structSize += items[i].minSize;
468 if (!pvStructInfo)
469 *pcbStructInfo = bytesNeeded;
470 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
471 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
473 BYTE *nextData;
475 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
476 pvStructInfo = *(BYTE **)pvStructInfo;
477 if (startingPointer)
478 nextData = (BYTE *)startingPointer;
479 else
480 nextData = (BYTE *)pvStructInfo + structSize;
481 memset(pvStructInfo, 0, structSize);
482 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
483 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
484 &cbDecoded);
489 else
491 SetLastError(CRYPT_E_ASN1_BADTAG);
492 ret = FALSE;
494 TRACE("returning %d (%08x)\n", ret, GetLastError());
495 return ret;
498 /* tag:
499 * The expected tag of the entire encoded array (usually a variant
500 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
501 * regardless of the tag seen.
502 * decodeFunc:
503 * used to decode each item in the array
504 * itemSize:
505 * is the minimum size of each decoded item
506 * hasPointer:
507 * indicates whether each item has a dynamic pointer
508 * pointerOffset:
509 * indicates the offset within itemSize at which the pointer exists
511 struct AsnArrayDescriptor
513 BYTE tag;
514 CryptDecodeObjectExFunc decodeFunc;
515 DWORD itemSize;
516 BOOL hasPointer;
517 DWORD pointerOffset;
520 struct AsnArrayItemSize
522 DWORD encodedLen;
523 DWORD size;
526 /* Decodes an array of like types into a struct GenericArray.
527 * The layout and decoding of the array are described by a struct
528 * AsnArrayDescriptor.
530 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
531 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
532 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
533 void *startingPointer)
535 BOOL ret = TRUE;
537 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
538 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
539 startingPointer);
541 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
543 DWORD dataLen;
545 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
547 DWORD bytesNeeded, cItems = 0;
548 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
549 /* There can be arbitrarily many items, but there is often only one.
551 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
553 bytesNeeded = sizeof(struct GenericArray);
554 if (dataLen)
556 const BYTE *ptr;
558 for (ptr = pbEncoded + 1 + lenBytes; ret &&
559 ptr - pbEncoded - 1 - lenBytes < dataLen; )
561 DWORD itemLenBytes, itemDataLen, size = 0;
563 itemLenBytes = GET_LEN_BYTES(ptr[1]);
564 /* Each item decoded may not tolerate extraneous bytes, so
565 * get the length of the next element and pass it directly.
567 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
568 &itemDataLen);
569 if (ret)
570 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
571 1 + itemLenBytes + itemDataLen,
572 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
573 &size);
574 if (ret)
576 DWORD nextLen;
578 cItems++;
579 if (itemSizes != &itemSize)
580 itemSizes = CryptMemRealloc(itemSizes,
581 cItems * sizeof(struct AsnArrayItemSize));
582 else
584 itemSizes =
585 CryptMemAlloc(
586 cItems * sizeof(struct AsnArrayItemSize));
587 if (itemSizes)
588 memcpy(itemSizes, &itemSize, sizeof(itemSize));
590 if (itemSizes)
592 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
593 + itemDataLen;
594 itemSizes[cItems - 1].size = size;
595 bytesNeeded += size;
596 ret = CRYPT_GetLen(ptr,
597 cbEncoded - (ptr - pbEncoded), &nextLen);
598 if (ret)
599 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
601 else
602 ret = FALSE;
606 if (ret)
608 if (!pvStructInfo)
609 *pcbStructInfo = bytesNeeded;
610 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
611 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
613 DWORD i;
614 BYTE *nextData;
615 const BYTE *ptr;
616 struct GenericArray *array;
618 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
619 pvStructInfo = *(BYTE **)pvStructInfo;
620 array = (struct GenericArray *)pvStructInfo;
621 array->cItems = cItems;
622 if (startingPointer)
623 array->rgItems = startingPointer;
624 else
625 array->rgItems = (BYTE *)array +
626 sizeof(struct GenericArray);
627 nextData = (BYTE *)array->rgItems +
628 array->cItems * arrayDesc->itemSize;
629 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
630 i < cItems && ptr - pbEncoded - 1 - lenBytes <
631 dataLen; i++)
633 if (arrayDesc->hasPointer)
634 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
635 + arrayDesc->pointerOffset) = nextData;
636 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
637 itemSizes[i].encodedLen,
638 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
639 array->rgItems + i * arrayDesc->itemSize,
640 &itemSizes[i].size);
641 if (ret)
643 DWORD nextLen;
645 nextData += itemSizes[i].size - arrayDesc->itemSize;
646 ret = CRYPT_GetLen(ptr,
647 cbEncoded - (ptr - pbEncoded), &nextLen);
648 if (ret)
649 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
654 if (itemSizes != &itemSize)
655 CryptMemFree(itemSizes);
658 else
660 SetLastError(CRYPT_E_ASN1_BADTAG);
661 ret = FALSE;
663 return ret;
666 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
667 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
668 * to CRYPT_E_ASN1_CORRUPT.
669 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
670 * set!
672 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
673 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
674 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
676 BOOL ret;
677 DWORD dataLen;
679 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
681 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
682 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
684 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
685 bytesNeeded += 1 + lenBytes + dataLen;
687 if (!pvStructInfo)
688 *pcbStructInfo = bytesNeeded;
689 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
690 pvStructInfo, pcbStructInfo, bytesNeeded)))
692 CRYPT_DER_BLOB *blob;
694 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
695 pvStructInfo = *(BYTE **)pvStructInfo;
696 blob = (CRYPT_DER_BLOB *)pvStructInfo;
697 blob->cbData = 1 + lenBytes + dataLen;
698 if (blob->cbData)
700 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
701 blob->pbData = (BYTE *)pbEncoded;
702 else
704 assert(blob->pbData);
705 memcpy(blob->pbData, pbEncoded, blob->cbData);
708 else
710 SetLastError(CRYPT_E_ASN1_CORRUPT);
711 ret = FALSE;
715 return ret;
718 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
719 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
720 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
721 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
723 BOOL ret;
725 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
726 pDecodePara, pvStructInfo, *pcbStructInfo);
728 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
729 * place.
731 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
732 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
733 pvStructInfo, pcbStructInfo);
734 if (ret && pvStructInfo)
736 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
738 if (blob->cbData)
740 DWORD i;
741 BYTE temp;
743 for (i = 0; i < blob->cbData / 2; i++)
745 temp = blob->pbData[i];
746 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
747 blob->pbData[blob->cbData - i - 1] = temp;
751 TRACE("returning %d (%08x)\n", ret, GetLastError());
752 return ret;
755 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
756 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
757 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
759 BOOL ret = TRUE;
761 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
762 pDecodePara, pvStructInfo, *pcbStructInfo);
764 __TRY
766 struct AsnDecodeSequenceItem items[] = {
767 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
768 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
769 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
770 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
771 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
772 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
773 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
774 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
775 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
776 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
779 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
780 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
781 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
782 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
783 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
785 __EXCEPT_PAGE_FAULT
787 SetLastError(STATUS_ACCESS_VIOLATION);
788 ret = FALSE;
790 __ENDTRY
792 TRACE("Returning %d (%08x)\n", ret, GetLastError());
793 return ret;
796 /* Internal function */
797 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
798 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
799 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
801 BOOL ret;
802 DWORD dataLen;
804 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
806 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
808 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
809 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
810 pvStructInfo, pcbStructInfo);
812 return ret;
815 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
816 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
817 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
819 BOOL ret;
821 struct AsnDecodeSequenceItem items[] = {
822 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
823 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
824 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
825 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
828 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
829 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
830 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
831 return ret;
834 /* Internal function */
835 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
836 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
837 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
839 BOOL ret;
840 DWORD dataLen;
842 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
844 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
846 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
847 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
848 pDecodePara, pvStructInfo, pcbStructInfo);
850 return ret;
853 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
854 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
855 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
857 BOOL ret = TRUE;
858 struct AsnDecodeSequenceItem items[] = {
859 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
860 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
861 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
862 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
863 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
864 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
865 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
866 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
867 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
868 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
869 Issuer.pbData) },
870 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
871 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
872 FALSE, 0 },
873 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
874 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
875 Subject.pbData) },
876 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
877 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
878 FALSE, TRUE, offsetof(CERT_INFO,
879 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
880 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
881 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
882 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
883 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
884 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
885 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
886 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
887 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
888 offsetof(CERT_INFO, rgExtension), 0 },
891 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
892 pDecodePara, pvStructInfo, *pcbStructInfo);
894 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
895 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
896 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
897 if (ret && pvStructInfo)
899 CERT_INFO *info;
901 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
902 info = *(CERT_INFO **)pvStructInfo;
903 else
904 info = (CERT_INFO *)pvStructInfo;
905 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
906 !info->Subject.cbData)
908 SetLastError(CRYPT_E_ASN1_CORRUPT);
909 /* Don't need to deallocate, because it should have failed on the
910 * first pass (and no memory was allocated.)
912 ret = FALSE;
916 TRACE("Returning %d (%08x)\n", ret, GetLastError());
917 return ret;
920 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
921 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
922 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
924 BOOL ret = TRUE;
926 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
927 pDecodePara, pvStructInfo, *pcbStructInfo);
929 __TRY
931 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
932 DWORD size = 0;
934 /* First try to decode it as a signed cert. */
935 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
936 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
937 (BYTE *)&signedCert, &size);
938 if (ret)
940 size = 0;
941 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
942 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
943 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
944 pcbStructInfo);
945 LocalFree(signedCert);
947 /* Failing that, try it as an unsigned cert */
948 if (!ret)
950 size = 0;
951 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
952 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
953 pDecodePara, pvStructInfo, pcbStructInfo);
956 __EXCEPT_PAGE_FAULT
958 SetLastError(STATUS_ACCESS_VIOLATION);
959 ret = FALSE;
961 __ENDTRY
963 TRACE("Returning %d (%08x)\n", ret, GetLastError());
964 return ret;
967 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
968 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
969 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
971 BOOL ret;
972 struct AsnDecodeSequenceItem items[] = {
973 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
974 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
975 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
976 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
977 sizeof(FILETIME), FALSE, FALSE, 0 },
978 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
979 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
980 offsetof(CRL_ENTRY, rgExtension), 0 },
982 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
984 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
985 *pcbStructInfo);
987 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
988 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
989 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
990 return ret;
993 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
994 * been set prior to calling.
996 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
997 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
998 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1000 BOOL ret;
1001 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1002 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1003 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1004 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1006 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1007 pDecodePara, pvStructInfo, *pcbStructInfo);
1009 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1010 pDecodePara, pvStructInfo, pcbStructInfo,
1011 entries ? entries->rgItems : NULL);
1012 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1013 return ret;
1016 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1017 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1018 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1020 struct AsnDecodeSequenceItem items[] = {
1021 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1022 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1023 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1024 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1025 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1026 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1027 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1028 Issuer.pbData) },
1029 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
1030 sizeof(FILETIME), FALSE, FALSE, 0 },
1031 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
1032 sizeof(FILETIME), TRUE, FALSE, 0 },
1033 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1034 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1035 offsetof(CRL_INFO, rgCRLEntry), 0 },
1036 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1037 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1038 offsetof(CRL_INFO, rgExtension), 0 },
1040 BOOL ret = TRUE;
1042 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1043 pDecodePara, pvStructInfo, *pcbStructInfo);
1045 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1046 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1047 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1049 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1050 return ret;
1053 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1054 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1055 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1057 BOOL ret = TRUE;
1059 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1060 pDecodePara, pvStructInfo, *pcbStructInfo);
1062 __TRY
1064 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1065 DWORD size = 0;
1067 /* First try to decode it as a signed crl. */
1068 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1069 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1070 (BYTE *)&signedCrl, &size);
1071 if (ret)
1073 size = 0;
1074 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1075 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1076 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1077 pvStructInfo, pcbStructInfo);
1078 LocalFree(signedCrl);
1080 /* Failing that, try it as an unsigned crl */
1081 if (!ret)
1083 size = 0;
1084 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1085 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1086 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1089 __EXCEPT_PAGE_FAULT
1091 SetLastError(STATUS_ACCESS_VIOLATION);
1092 ret = FALSE;
1094 __ENDTRY
1096 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1097 return ret;
1100 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1101 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1102 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1104 BOOL ret = TRUE;
1106 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1107 pDecodePara, pvStructInfo, *pcbStructInfo);
1109 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1111 DWORD dataLen;
1113 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1115 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1116 DWORD bytesNeeded = sizeof(LPSTR);
1118 if (dataLen)
1120 /* The largest possible string for the first two components
1121 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1123 char firstTwo[6];
1124 const BYTE *ptr;
1126 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1127 pbEncoded[1 + lenBytes] / 40,
1128 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1129 * 40);
1130 bytesNeeded += strlen(firstTwo) + 1;
1131 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1132 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1134 /* large enough for ".4000000" */
1135 char str[9];
1136 int val = 0;
1138 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1139 (*ptr & 0x80))
1141 val <<= 7;
1142 val |= *ptr & 0x7f;
1143 ptr++;
1145 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1146 (*ptr & 0x80))
1148 SetLastError(CRYPT_E_ASN1_CORRUPT);
1149 ret = FALSE;
1151 else
1153 val <<= 7;
1154 val |= *ptr++;
1155 snprintf(str, sizeof(str), ".%d", val);
1156 bytesNeeded += strlen(str);
1160 if (!pvStructInfo)
1161 *pcbStructInfo = bytesNeeded;
1162 else if (*pcbStructInfo < bytesNeeded)
1164 *pcbStructInfo = bytesNeeded;
1165 SetLastError(ERROR_MORE_DATA);
1166 ret = FALSE;
1168 else
1170 if (dataLen)
1172 const BYTE *ptr;
1173 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1175 *pszObjId = 0;
1176 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1177 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1178 40) * 40);
1179 pszObjId += strlen(pszObjId);
1180 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1181 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1183 int val = 0;
1185 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1186 (*ptr & 0x80))
1188 val <<= 7;
1189 val |= *ptr & 0x7f;
1190 ptr++;
1192 val <<= 7;
1193 val |= *ptr++;
1194 sprintf(pszObjId, ".%d", val);
1195 pszObjId += strlen(pszObjId);
1198 else
1199 *(LPSTR *)pvStructInfo = NULL;
1200 *pcbStructInfo = bytesNeeded;
1204 return ret;
1207 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1208 * ahead of time!
1210 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1211 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1212 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1214 struct AsnDecodeSequenceItem items[] = {
1215 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1216 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1217 offsetof(CERT_EXTENSION, pszObjId), 0 },
1218 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1219 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1220 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1221 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1222 offsetof(CERT_EXTENSION, Value.pbData) },
1224 BOOL ret = TRUE;
1225 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1227 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1228 *pcbStructInfo);
1230 if (ext)
1231 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1232 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1233 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1234 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1235 if (ext)
1236 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1237 debugstr_a(ext->pszObjId));
1238 TRACE("returning %d (%08x)\n", ret, GetLastError());
1239 return ret;
1242 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1243 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1244 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1246 BOOL ret = TRUE;
1247 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1248 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1249 offsetof(CERT_EXTENSION, pszObjId) };
1250 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1252 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1253 pDecodePara, pvStructInfo, *pcbStructInfo);
1255 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1256 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1257 return ret;
1260 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1261 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1262 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1264 BOOL ret = TRUE;
1266 __TRY
1268 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1269 lpszStructType, pbEncoded, cbEncoded,
1270 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1271 if (ret && pvStructInfo)
1273 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1274 pcbStructInfo, *pcbStructInfo);
1275 if (ret)
1277 CERT_EXTENSIONS *exts;
1279 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1280 pvStructInfo = *(BYTE **)pvStructInfo;
1281 exts = (CERT_EXTENSIONS *)pvStructInfo;
1282 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1283 sizeof(CERT_EXTENSIONS));
1284 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1285 lpszStructType, pbEncoded, cbEncoded,
1286 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1287 pcbStructInfo);
1291 __EXCEPT_PAGE_FAULT
1293 SetLastError(STATUS_ACCESS_VIOLATION);
1294 ret = FALSE;
1296 __ENDTRY
1297 return ret;
1300 /* Warning: this assumes the address of value->Value.pbData is already set, in
1301 * order to avoid overwriting memory. (In some cases, it may change it, if it
1302 * doesn't copy anything to memory.) Be sure to set it correctly!
1304 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1305 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1306 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1308 BOOL ret = TRUE;
1309 DWORD dataLen;
1310 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1312 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1314 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1315 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1317 switch (pbEncoded[0])
1319 case ASN_OCTETSTRING:
1320 valueType = CERT_RDN_OCTET_STRING;
1321 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1322 bytesNeeded += dataLen;
1323 break;
1324 case ASN_NUMERICSTRING:
1325 valueType = CERT_RDN_NUMERIC_STRING;
1326 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1327 bytesNeeded += dataLen;
1328 break;
1329 case ASN_PRINTABLESTRING:
1330 valueType = CERT_RDN_PRINTABLE_STRING;
1331 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1332 bytesNeeded += dataLen;
1333 break;
1334 case ASN_IA5STRING:
1335 valueType = CERT_RDN_IA5_STRING;
1336 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1337 bytesNeeded += dataLen;
1338 break;
1339 case ASN_T61STRING:
1340 valueType = CERT_RDN_T61_STRING;
1341 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1342 bytesNeeded += dataLen;
1343 break;
1344 case ASN_VIDEOTEXSTRING:
1345 valueType = CERT_RDN_VIDEOTEX_STRING;
1346 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1347 bytesNeeded += dataLen;
1348 break;
1349 case ASN_GRAPHICSTRING:
1350 valueType = CERT_RDN_GRAPHIC_STRING;
1351 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1352 bytesNeeded += dataLen;
1353 break;
1354 case ASN_VISIBLESTRING:
1355 valueType = CERT_RDN_VISIBLE_STRING;
1356 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1357 bytesNeeded += dataLen;
1358 break;
1359 case ASN_GENERALSTRING:
1360 valueType = CERT_RDN_GENERAL_STRING;
1361 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1362 bytesNeeded += dataLen;
1363 break;
1364 case ASN_UNIVERSALSTRING:
1365 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1366 SetLastError(CRYPT_E_ASN1_BADTAG);
1367 return FALSE;
1368 case ASN_BMPSTRING:
1369 valueType = CERT_RDN_BMP_STRING;
1370 bytesNeeded += dataLen;
1371 break;
1372 case ASN_UTF8STRING:
1373 valueType = CERT_RDN_UTF8_STRING;
1374 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1375 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1376 break;
1377 default:
1378 SetLastError(CRYPT_E_ASN1_BADTAG);
1379 return FALSE;
1382 if (!value)
1383 *pcbStructInfo = bytesNeeded;
1384 else if (*pcbStructInfo < bytesNeeded)
1386 *pcbStructInfo = bytesNeeded;
1387 SetLastError(ERROR_MORE_DATA);
1388 ret = FALSE;
1390 else
1392 *pcbStructInfo = bytesNeeded;
1393 value->dwValueType = valueType;
1394 if (dataLen)
1396 DWORD i;
1398 assert(value->Value.pbData);
1399 switch (pbEncoded[0])
1401 case ASN_OCTETSTRING:
1402 case ASN_NUMERICSTRING:
1403 case ASN_PRINTABLESTRING:
1404 case ASN_IA5STRING:
1405 case ASN_T61STRING:
1406 case ASN_VIDEOTEXSTRING:
1407 case ASN_GRAPHICSTRING:
1408 case ASN_VISIBLESTRING:
1409 case ASN_GENERALSTRING:
1410 value->Value.cbData = dataLen;
1411 if (dataLen)
1413 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1414 memcpy(value->Value.pbData,
1415 pbEncoded + 1 + lenBytes, dataLen);
1416 else
1417 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1418 lenBytes;
1420 break;
1421 case ASN_BMPSTRING:
1423 LPWSTR str = (LPWSTR)value->Value.pbData;
1425 value->Value.cbData = dataLen;
1426 for (i = 0; i < dataLen / 2; i++)
1427 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1428 pbEncoded[1 + lenBytes + 2 * i + 1];
1429 break;
1431 case ASN_UTF8STRING:
1433 LPWSTR str = (LPWSTR)value->Value.pbData;
1435 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1436 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1437 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1438 break;
1442 else
1444 value->Value.cbData = 0;
1445 value->Value.pbData = NULL;
1449 return ret;
1452 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1453 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1454 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1456 BOOL ret = TRUE;
1458 __TRY
1460 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1461 lpszStructType, pbEncoded, cbEncoded,
1462 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1463 if (ret && pvStructInfo)
1465 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1466 pcbStructInfo, *pcbStructInfo);
1467 if (ret)
1469 CERT_NAME_VALUE *value;
1471 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1472 pvStructInfo = *(BYTE **)pvStructInfo;
1473 value = (CERT_NAME_VALUE *)pvStructInfo;
1474 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1475 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1476 lpszStructType, pbEncoded, cbEncoded,
1477 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1478 pcbStructInfo);
1482 __EXCEPT_PAGE_FAULT
1484 SetLastError(STATUS_ACCESS_VIOLATION);
1485 ret = FALSE;
1487 __ENDTRY
1488 return ret;
1491 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1492 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1493 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1494 void *pvStructInfo, DWORD *pcbStructInfo)
1496 BOOL ret = TRUE;
1497 DWORD dataLen;
1498 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1500 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1502 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1503 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1505 switch (pbEncoded[0])
1507 case ASN_NUMERICSTRING:
1508 valueType = CERT_RDN_NUMERIC_STRING;
1509 bytesNeeded += dataLen * 2;
1510 break;
1511 case ASN_PRINTABLESTRING:
1512 valueType = CERT_RDN_PRINTABLE_STRING;
1513 bytesNeeded += dataLen * 2;
1514 break;
1515 case ASN_IA5STRING:
1516 valueType = CERT_RDN_IA5_STRING;
1517 bytesNeeded += dataLen * 2;
1518 break;
1519 case ASN_T61STRING:
1520 valueType = CERT_RDN_T61_STRING;
1521 bytesNeeded += dataLen * 2;
1522 break;
1523 case ASN_VIDEOTEXSTRING:
1524 valueType = CERT_RDN_VIDEOTEX_STRING;
1525 bytesNeeded += dataLen * 2;
1526 break;
1527 case ASN_GRAPHICSTRING:
1528 valueType = CERT_RDN_GRAPHIC_STRING;
1529 bytesNeeded += dataLen * 2;
1530 break;
1531 case ASN_VISIBLESTRING:
1532 valueType = CERT_RDN_VISIBLE_STRING;
1533 bytesNeeded += dataLen * 2;
1534 break;
1535 case ASN_GENERALSTRING:
1536 valueType = CERT_RDN_GENERAL_STRING;
1537 bytesNeeded += dataLen * 2;
1538 break;
1539 case ASN_UNIVERSALSTRING:
1540 valueType = CERT_RDN_UNIVERSAL_STRING;
1541 bytesNeeded += dataLen / 2;
1542 break;
1543 case ASN_BMPSTRING:
1544 valueType = CERT_RDN_BMP_STRING;
1545 bytesNeeded += dataLen;
1546 break;
1547 case ASN_UTF8STRING:
1548 valueType = CERT_RDN_UTF8_STRING;
1549 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1550 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1551 break;
1552 default:
1553 SetLastError(CRYPT_E_ASN1_BADTAG);
1554 return FALSE;
1557 if (!value)
1558 *pcbStructInfo = bytesNeeded;
1559 else if (*pcbStructInfo < bytesNeeded)
1561 *pcbStructInfo = bytesNeeded;
1562 SetLastError(ERROR_MORE_DATA);
1563 ret = FALSE;
1565 else
1567 *pcbStructInfo = bytesNeeded;
1568 value->dwValueType = valueType;
1569 if (dataLen)
1571 DWORD i;
1572 LPWSTR str = (LPWSTR)value->Value.pbData;
1574 assert(value->Value.pbData);
1575 switch (pbEncoded[0])
1577 case ASN_NUMERICSTRING:
1578 case ASN_PRINTABLESTRING:
1579 case ASN_IA5STRING:
1580 case ASN_T61STRING:
1581 case ASN_VIDEOTEXSTRING:
1582 case ASN_GRAPHICSTRING:
1583 case ASN_VISIBLESTRING:
1584 case ASN_GENERALSTRING:
1585 value->Value.cbData = dataLen * 2;
1586 for (i = 0; i < dataLen; i++)
1587 str[i] = pbEncoded[1 + lenBytes + i];
1588 break;
1589 case ASN_UNIVERSALSTRING:
1590 value->Value.cbData = dataLen / 2;
1591 for (i = 0; i < dataLen / 4; i++)
1592 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1593 | pbEncoded[1 + lenBytes + 2 * i + 3];
1594 break;
1595 case ASN_BMPSTRING:
1596 value->Value.cbData = dataLen;
1597 for (i = 0; i < dataLen / 2; i++)
1598 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1599 pbEncoded[1 + lenBytes + 2 * i + 1];
1600 break;
1601 case ASN_UTF8STRING:
1602 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1603 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1604 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1605 break;
1608 else
1610 value->Value.cbData = 0;
1611 value->Value.pbData = NULL;
1615 return ret;
1618 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1619 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1620 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1622 BOOL ret = TRUE;
1624 __TRY
1626 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1627 lpszStructType, pbEncoded, cbEncoded,
1628 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1629 if (ret && pvStructInfo)
1631 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1632 pcbStructInfo, *pcbStructInfo);
1633 if (ret)
1635 CERT_NAME_VALUE *value;
1637 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1638 pvStructInfo = *(BYTE **)pvStructInfo;
1639 value = (CERT_NAME_VALUE *)pvStructInfo;
1640 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1641 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1642 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1643 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1644 pcbStructInfo);
1648 __EXCEPT_PAGE_FAULT
1650 SetLastError(STATUS_ACCESS_VIOLATION);
1651 ret = FALSE;
1653 __ENDTRY
1654 return ret;
1657 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1658 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1659 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1661 BOOL ret;
1662 struct AsnDecodeSequenceItem items[] = {
1663 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1664 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1665 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1666 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1667 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1668 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1670 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1672 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1673 pvStructInfo, *pcbStructInfo);
1675 if (attr)
1676 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1677 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1678 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1679 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1680 if (attr)
1682 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1683 debugstr_a(attr->pszObjId));
1684 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1686 TRACE("returning %d (%08x)\n", ret, GetLastError());
1687 return ret;
1690 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1691 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1692 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1694 BOOL ret = TRUE;
1695 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1696 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1697 offsetof(CERT_RDN_ATTR, pszObjId) };
1698 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1700 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1701 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1702 return ret;
1705 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1706 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1707 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1709 BOOL ret = TRUE;
1711 __TRY
1713 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1714 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1715 offsetof(CERT_RDN, rgRDNAttr) };
1717 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1718 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1720 __EXCEPT_PAGE_FAULT
1722 SetLastError(STATUS_ACCESS_VIOLATION);
1723 ret = FALSE;
1725 __ENDTRY
1726 return ret;
1729 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
1730 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1731 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1733 BOOL ret;
1734 struct AsnDecodeSequenceItem items[] = {
1735 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1736 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1737 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1738 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1739 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1740 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1742 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1744 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1745 pvStructInfo, *pcbStructInfo);
1747 if (attr)
1748 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1749 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1750 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1751 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1752 if (attr)
1754 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1755 debugstr_a(attr->pszObjId));
1756 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1758 TRACE("returning %d (%08x)\n", ret, GetLastError());
1759 return ret;
1762 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
1763 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1764 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1766 BOOL ret = TRUE;
1767 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1768 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1769 offsetof(CERT_RDN_ATTR, pszObjId) };
1770 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1772 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1773 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1774 return ret;
1777 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1778 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1779 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1781 BOOL ret = TRUE;
1783 __TRY
1785 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1786 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1787 offsetof(CERT_RDN, rgRDNAttr) };
1789 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1790 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1792 __EXCEPT_PAGE_FAULT
1794 SetLastError(STATUS_ACCESS_VIOLATION);
1795 ret = FALSE;
1797 __ENDTRY
1798 return ret;
1801 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1802 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1803 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1805 BOOL ret = TRUE;
1806 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1808 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1809 pDecodePara, pvStructInfo, *pcbStructInfo);
1811 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1812 bytesNeeded += cbEncoded;
1813 if (!pvStructInfo)
1814 *pcbStructInfo = bytesNeeded;
1815 else if (*pcbStructInfo < bytesNeeded)
1817 SetLastError(ERROR_MORE_DATA);
1818 *pcbStructInfo = bytesNeeded;
1819 ret = FALSE;
1821 else
1823 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1825 *pcbStructInfo = bytesNeeded;
1826 blob->cbData = cbEncoded;
1827 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1828 blob->pbData = (LPBYTE)pbEncoded;
1829 else
1831 assert(blob->pbData);
1832 memcpy(blob->pbData, pbEncoded, blob->cbData);
1835 return ret;
1838 static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType,
1839 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1840 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1842 BOOL ret;
1843 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1844 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB), TRUE,
1845 offsetof(CRYPT_DER_BLOB, pbData) };
1846 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1848 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1849 pDecodePara, pvStructInfo, *pcbStructInfo);
1851 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1852 pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
1853 return ret;
1856 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1857 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1858 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1860 BOOL ret = FALSE;
1862 __TRY
1864 struct AsnDecodeSequenceItem items[] = {
1865 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1866 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1867 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1868 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1869 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1870 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1872 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1874 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1875 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1876 pDecodePara, pvStructInfo, pcbStructInfo, attr ? attr->pszObjId :
1877 NULL);
1879 __EXCEPT_PAGE_FAULT
1881 SetLastError(STATUS_ACCESS_VIOLATION);
1883 __ENDTRY
1884 TRACE("returning %d\n", ret);
1885 return ret;
1888 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal(
1889 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1890 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1891 void *pvStructInfo, DWORD *pcbStructInfo)
1893 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1894 CRYPT_AsnDecodePKCSAttribute, sizeof(CRYPT_ATTRIBUTE), TRUE,
1895 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
1896 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1897 BOOL ret;
1899 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1900 pDecodePara, pvStructInfo, pcbStructInfo, attrs ? attrs->rgAttr :
1901 NULL);
1902 return ret;
1905 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
1906 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1907 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1909 BOOL ret = FALSE;
1911 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1912 pDecodePara, pvStructInfo, *pcbStructInfo);
1914 __TRY
1916 DWORD bytesNeeded;
1918 if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1919 lpszStructType, pbEncoded, cbEncoded,
1920 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1922 if (!pvStructInfo)
1923 *pcbStructInfo = bytesNeeded;
1924 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1925 pvStructInfo, pcbStructInfo, bytesNeeded)))
1927 PCRYPT_ATTRIBUTES attrs;
1929 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1930 pvStructInfo = *(BYTE **)pvStructInfo;
1931 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1932 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
1933 sizeof(CRYPT_ATTRIBUTES));
1934 ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1935 lpszStructType, pbEncoded, cbEncoded,
1936 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1937 &bytesNeeded);
1941 __EXCEPT_PAGE_FAULT
1943 SetLastError(STATUS_ACCESS_VIOLATION);
1945 __ENDTRY
1946 TRACE("returning %d\n", ret);
1947 return ret;
1950 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1951 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1952 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1954 CRYPT_ALGORITHM_IDENTIFIER *algo =
1955 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1956 BOOL ret = TRUE;
1957 struct AsnDecodeSequenceItem items[] = {
1958 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1959 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1960 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1961 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1962 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1963 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1966 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1967 pDecodePara, pvStructInfo, *pcbStructInfo);
1969 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1970 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1971 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1972 if (ret && pvStructInfo)
1974 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1975 debugstr_a(algo->pszObjId));
1977 return ret;
1980 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1981 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1982 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1984 BOOL ret = TRUE;
1985 struct AsnDecodeSequenceItem items[] = {
1986 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1987 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1988 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1989 Algorithm.pszObjId) },
1990 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1991 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1992 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1994 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1996 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1997 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1998 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1999 info->Algorithm.Parameters.pbData : NULL);
2000 return ret;
2003 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2004 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2005 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2007 BOOL ret = TRUE;
2009 __TRY
2011 DWORD bytesNeeded;
2013 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2014 lpszStructType, pbEncoded, cbEncoded,
2015 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2017 if (!pvStructInfo)
2018 *pcbStructInfo = bytesNeeded;
2019 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2020 pvStructInfo, pcbStructInfo, bytesNeeded)))
2022 PCERT_PUBLIC_KEY_INFO info;
2024 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2025 pvStructInfo = *(BYTE **)pvStructInfo;
2026 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2027 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2028 sizeof(CERT_PUBLIC_KEY_INFO);
2029 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2030 lpszStructType, pbEncoded, cbEncoded,
2031 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2032 &bytesNeeded);
2036 __EXCEPT_PAGE_FAULT
2038 SetLastError(STATUS_ACCESS_VIOLATION);
2039 ret = FALSE;
2041 __ENDTRY
2042 return ret;
2045 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2046 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2047 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2049 BOOL ret;
2051 if (cbEncoded < 3)
2053 SetLastError(CRYPT_E_ASN1_CORRUPT);
2054 return FALSE;
2056 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2058 SetLastError(CRYPT_E_ASN1_CORRUPT);
2059 return FALSE;
2061 if (pbEncoded[1] > 1)
2063 SetLastError(CRYPT_E_ASN1_CORRUPT);
2064 return FALSE;
2066 if (!pvStructInfo)
2068 *pcbStructInfo = sizeof(BOOL);
2069 ret = TRUE;
2071 else if (*pcbStructInfo < sizeof(BOOL))
2073 *pcbStructInfo = sizeof(BOOL);
2074 SetLastError(ERROR_MORE_DATA);
2075 ret = FALSE;
2077 else
2079 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2080 ret = TRUE;
2082 TRACE("returning %d (%08x)\n", ret, GetLastError());
2083 return ret;
2086 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
2087 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2088 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2090 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2091 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2092 BOOL ret;
2094 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2095 pDecodePara, pvStructInfo, *pcbStructInfo);
2097 if (cbEncoded < 2)
2099 SetLastError(CRYPT_E_ASN1_CORRUPT);
2100 return FALSE;
2102 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
2104 SetLastError(CRYPT_E_ASN1_BADTAG);
2105 return FALSE;
2107 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2108 if (1 + lenBytes > cbEncoded)
2110 SetLastError(CRYPT_E_ASN1_CORRUPT);
2111 return FALSE;
2113 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2115 switch (pbEncoded[0] & ASN_TYPE_MASK)
2117 case 1: /* rfc822Name */
2118 case 2: /* dNSName */
2119 case 6: /* uniformResourceIdentifier */
2120 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2121 break;
2122 case 7: /* iPAddress */
2123 bytesNeeded += dataLen;
2124 break;
2125 case 8: /* registeredID */
2126 /* FIXME: decode as OID */
2127 case 0: /* otherName */
2128 case 4: /* directoryName */
2129 FIXME("stub\n");
2130 SetLastError(CRYPT_E_ASN1_BADTAG);
2131 ret = FALSE;
2132 break;
2133 case 3: /* x400Address, unimplemented */
2134 case 5: /* ediPartyName, unimplemented */
2135 SetLastError(CRYPT_E_ASN1_BADTAG);
2136 ret = FALSE;
2137 break;
2138 default:
2139 SetLastError(CRYPT_E_ASN1_CORRUPT);
2140 ret = FALSE;
2142 if (ret)
2144 if (!entry)
2145 *pcbStructInfo = bytesNeeded;
2146 else if (*pcbStructInfo < bytesNeeded)
2148 *pcbStructInfo = bytesNeeded;
2149 SetLastError(ERROR_MORE_DATA);
2150 ret = FALSE;
2152 else
2154 *pcbStructInfo = bytesNeeded;
2155 /* MS used values one greater than the asn1 ones.. sigh */
2156 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2157 switch (pbEncoded[0] & ASN_TYPE_MASK)
2159 case 1: /* rfc822Name */
2160 case 2: /* dNSName */
2161 case 6: /* uniformResourceIdentifier */
2163 DWORD i;
2165 for (i = 0; i < dataLen; i++)
2166 entry->u.pwszURL[i] =
2167 (WCHAR)pbEncoded[1 + lenBytes + i];
2168 entry->u.pwszURL[i] = 0;
2169 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2170 debugstr_w(entry->u.pwszURL));
2171 break;
2173 case 7: /* iPAddress */
2174 /* The next data pointer is in the pwszURL spot, that is,
2175 * the first 4 bytes. Need to move it to the next spot.
2177 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2178 entry->u.IPAddress.cbData = dataLen;
2179 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2180 dataLen);
2181 break;
2186 return ret;
2189 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2190 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2191 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2193 BOOL ret = TRUE;
2194 struct AsnArrayDescriptor arrayDesc = { 0,
2195 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2196 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2197 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2199 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2200 pDecodePara, pvStructInfo, *pcbStructInfo);
2202 if (info)
2203 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2204 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2205 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2206 return ret;
2209 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2210 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2211 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2213 BOOL ret;
2215 __TRY
2217 struct AsnDecodeSequenceItem items[] = {
2218 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2219 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2220 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2221 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2222 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2223 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2224 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2225 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2226 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2227 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2228 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2231 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2232 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2233 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2235 __EXCEPT_PAGE_FAULT
2237 SetLastError(STATUS_ACCESS_VIOLATION);
2238 ret = FALSE;
2240 __ENDTRY
2241 return ret;
2244 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2245 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2246 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2248 BOOL ret;
2250 __TRY
2252 struct AsnDecodeSequenceItem items[] = {
2253 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2254 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2255 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2256 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2257 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2258 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2259 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2260 AuthorityCertIssuer.rgAltEntry), 0 },
2261 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2262 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2263 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2264 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2265 AuthorityCertSerialNumber.pbData), 0 },
2268 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2269 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2270 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2272 __EXCEPT_PAGE_FAULT
2274 SetLastError(STATUS_ACCESS_VIOLATION);
2275 ret = FALSE;
2277 __ENDTRY
2278 return ret;
2281 static BOOL WINAPI CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType,
2282 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2283 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2285 BOOL ret;
2286 DWORD dataLen;
2288 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2289 pDecodePara, pvStructInfo, *pcbStructInfo);
2291 /* The caller has already checked the tag, no need to check it again.
2292 * Check the outer length is valid by calling CRYPT_GetLen:
2294 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2296 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2297 DWORD innerLen;
2299 pbEncoded += 1 + lenBytes;
2300 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2301 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2303 ret = CRYPT_AsnDecodeCopyBytes(dwCertEncodingType, NULL,
2304 pbEncoded, dataLen, dwFlags, pDecodePara, pvStructInfo,
2305 pcbStructInfo);
2308 return ret;
2311 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfoInternal(
2312 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2313 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2314 void *pvStructInfo, DWORD *pcbStructInfo)
2316 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2317 struct AsnDecodeSequenceItem items[] = {
2318 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2319 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
2320 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2321 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2322 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2323 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2324 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2327 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2328 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2329 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->pszObjId : NULL);
2332 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2333 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2334 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2336 BOOL ret = FALSE;
2338 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2339 pDecodePara, pvStructInfo, *pcbStructInfo);
2341 __TRY
2343 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2344 lpszStructType, pbEncoded, cbEncoded,
2345 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
2346 if (ret && pvStructInfo)
2348 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2349 pcbStructInfo, *pcbStructInfo);
2350 if (ret)
2352 CRYPT_CONTENT_INFO *info;
2354 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2355 pvStructInfo = *(BYTE **)pvStructInfo;
2356 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2357 info->pszObjId = (LPSTR)((BYTE *)info +
2358 sizeof(CRYPT_CONTENT_INFO));
2359 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2360 lpszStructType, pbEncoded, cbEncoded,
2361 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2362 pcbStructInfo);
2366 __EXCEPT_PAGE_FAULT
2368 SetLastError(STATUS_ACCESS_VIOLATION);
2370 __ENDTRY
2371 return ret;
2374 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2375 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2376 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2378 BOOL ret;
2379 struct AsnDecodeSequenceItem items[] = {
2380 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version), CRYPT_AsnDecodeInt,
2381 sizeof(DWORD), FALSE, FALSE, 0, 0 },
2382 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2383 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2384 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2385 0 },
2386 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2387 CRYPT_AsnDecodePKCSContentInfoInternal,
2388 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2389 ContentInfo.pszObjId), 0 },
2390 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2391 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2392 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2395 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
2396 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2397 pDecodePara, digestedData, pcbDigestedData, NULL);
2398 return ret;
2401 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2402 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2403 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2405 BOOL ret = TRUE;
2407 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2408 pDecodePara, pvStructInfo, *pcbStructInfo);
2410 __TRY
2412 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2413 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2414 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2416 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2417 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2419 __EXCEPT_PAGE_FAULT
2421 SetLastError(STATUS_ACCESS_VIOLATION);
2422 ret = FALSE;
2424 __ENDTRY
2425 return ret;
2428 struct PATH_LEN_CONSTRAINT
2430 BOOL fPathLenConstraint;
2431 DWORD dwPathLenConstraint;
2434 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2435 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2436 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2438 BOOL ret = TRUE;
2440 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2441 pvStructInfo, *pcbStructInfo);
2443 if (cbEncoded)
2445 if (pbEncoded[0] == ASN_INTEGER)
2447 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2449 if (!pvStructInfo)
2450 *pcbStructInfo = bytesNeeded;
2451 else if (*pcbStructInfo < bytesNeeded)
2453 SetLastError(ERROR_MORE_DATA);
2454 *pcbStructInfo = bytesNeeded;
2455 ret = FALSE;
2457 else
2459 struct PATH_LEN_CONSTRAINT *constraint =
2460 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2461 DWORD size = sizeof(constraint->dwPathLenConstraint);
2463 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2464 pbEncoded, cbEncoded, 0, NULL,
2465 &constraint->dwPathLenConstraint, &size);
2466 if (ret)
2467 constraint->fPathLenConstraint = TRUE;
2468 TRACE("got an int, dwPathLenConstraint is %d\n",
2469 constraint->dwPathLenConstraint);
2472 else
2474 SetLastError(CRYPT_E_ASN1_CORRUPT);
2475 ret = FALSE;
2478 TRACE("returning %d (%08x)\n", ret, GetLastError());
2479 return ret;
2482 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2483 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2484 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2486 BOOL ret;
2487 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2488 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2489 offsetof(CERT_NAME_BLOB, pbData) };
2490 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2492 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2493 pDecodePara, pvStructInfo, *pcbStructInfo);
2495 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2496 pDecodePara, pvStructInfo, pcbStructInfo,
2497 entries ? entries->rgItems : NULL);
2498 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2499 return ret;
2502 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2503 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2504 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2506 BOOL ret;
2508 __TRY
2510 struct AsnDecodeSequenceItem items[] = {
2511 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2512 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2513 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2514 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2515 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2516 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2517 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2518 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2519 sizeof(struct GenericArray), TRUE, TRUE,
2520 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2523 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2524 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2525 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2527 __EXCEPT_PAGE_FAULT
2529 SetLastError(STATUS_ACCESS_VIOLATION);
2530 ret = FALSE;
2532 __ENDTRY
2533 return ret;
2536 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2537 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2538 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2540 BOOL ret;
2542 __TRY
2544 struct AsnDecodeSequenceItem items[] = {
2545 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2546 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2547 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2548 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2549 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2552 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2553 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2554 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2556 __EXCEPT_PAGE_FAULT
2558 SetLastError(STATUS_ACCESS_VIOLATION);
2559 ret = FALSE;
2561 __ENDTRY
2562 return ret;
2565 #define RSA1_MAGIC 0x31415352
2567 struct DECODED_RSA_PUB_KEY
2569 DWORD pubexp;
2570 CRYPT_INTEGER_BLOB modulus;
2573 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2574 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2575 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2577 BOOL ret;
2579 __TRY
2581 struct AsnDecodeSequenceItem items[] = {
2582 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2583 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2584 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2585 0 },
2586 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2587 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2589 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2590 DWORD size = 0;
2592 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2593 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2594 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2595 if (ret)
2597 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2598 decodedKey->modulus.cbData;
2600 if (!pvStructInfo)
2602 *pcbStructInfo = bytesNeeded;
2603 ret = TRUE;
2605 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2606 pvStructInfo, pcbStructInfo, bytesNeeded)))
2608 BLOBHEADER *hdr;
2609 RSAPUBKEY *rsaPubKey;
2611 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2612 pvStructInfo = *(BYTE **)pvStructInfo;
2613 hdr = (BLOBHEADER *)pvStructInfo;
2614 hdr->bType = PUBLICKEYBLOB;
2615 hdr->bVersion = CUR_BLOB_VERSION;
2616 hdr->reserved = 0;
2617 hdr->aiKeyAlg = CALG_RSA_KEYX;
2618 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2619 sizeof(BLOBHEADER));
2620 rsaPubKey->magic = RSA1_MAGIC;
2621 rsaPubKey->pubexp = decodedKey->pubexp;
2622 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2623 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2624 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2625 decodedKey->modulus.cbData);
2627 LocalFree(decodedKey);
2630 __EXCEPT_PAGE_FAULT
2632 SetLastError(STATUS_ACCESS_VIOLATION);
2633 ret = FALSE;
2635 __ENDTRY
2636 return ret;
2639 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2640 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2641 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2643 BOOL ret;
2644 DWORD bytesNeeded, dataLen;
2646 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2647 pDecodePara, pvStructInfo, *pcbStructInfo);
2649 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2651 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2652 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2653 else
2654 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2655 if (!pvStructInfo)
2656 *pcbStructInfo = bytesNeeded;
2657 else if (*pcbStructInfo < bytesNeeded)
2659 SetLastError(ERROR_MORE_DATA);
2660 *pcbStructInfo = bytesNeeded;
2661 ret = FALSE;
2663 else
2665 CRYPT_DATA_BLOB *blob;
2666 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2668 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2669 blob->cbData = dataLen;
2670 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2671 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2672 else
2674 assert(blob->pbData);
2675 if (blob->cbData)
2676 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2677 blob->cbData);
2681 return ret;
2684 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2685 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2686 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2688 BOOL ret;
2690 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2691 pDecodePara, pvStructInfo, *pcbStructInfo);
2693 __TRY
2695 DWORD bytesNeeded;
2697 if (!cbEncoded)
2699 SetLastError(CRYPT_E_ASN1_CORRUPT);
2700 ret = FALSE;
2702 else if (pbEncoded[0] != ASN_OCTETSTRING)
2704 SetLastError(CRYPT_E_ASN1_BADTAG);
2705 ret = FALSE;
2707 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2708 lpszStructType, pbEncoded, cbEncoded,
2709 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2711 if (!pvStructInfo)
2712 *pcbStructInfo = bytesNeeded;
2713 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2714 pvStructInfo, pcbStructInfo, bytesNeeded)))
2716 CRYPT_DATA_BLOB *blob;
2718 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2719 pvStructInfo = *(BYTE **)pvStructInfo;
2720 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2721 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2722 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2723 lpszStructType, pbEncoded, cbEncoded,
2724 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2725 &bytesNeeded);
2729 __EXCEPT_PAGE_FAULT
2731 SetLastError(STATUS_ACCESS_VIOLATION);
2732 ret = FALSE;
2734 __ENDTRY
2735 return ret;
2738 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2739 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2740 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2742 BOOL ret;
2744 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2745 pDecodePara, pvStructInfo, *pcbStructInfo);
2747 if (pbEncoded[0] == ASN_BITSTRING)
2749 DWORD bytesNeeded, dataLen;
2751 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2753 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2754 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2755 else
2756 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2757 if (!pvStructInfo)
2758 *pcbStructInfo = bytesNeeded;
2759 else if (*pcbStructInfo < bytesNeeded)
2761 *pcbStructInfo = bytesNeeded;
2762 SetLastError(ERROR_MORE_DATA);
2763 ret = FALSE;
2765 else
2767 CRYPT_BIT_BLOB *blob;
2769 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2770 blob->cbData = dataLen - 1;
2771 blob->cUnusedBits = *(pbEncoded + 1 +
2772 GET_LEN_BYTES(pbEncoded[1]));
2773 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2775 blob->pbData = (BYTE *)pbEncoded + 2 +
2776 GET_LEN_BYTES(pbEncoded[1]);
2778 else
2780 assert(blob->pbData);
2781 if (blob->cbData)
2783 BYTE mask = 0xff << blob->cUnusedBits;
2785 memcpy(blob->pbData, pbEncoded + 2 +
2786 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2787 blob->pbData[blob->cbData - 1] &= mask;
2793 else
2795 SetLastError(CRYPT_E_ASN1_BADTAG);
2796 ret = FALSE;
2798 TRACE("returning %d (%08x)\n", ret, GetLastError());
2799 return ret;
2802 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2803 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2804 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2806 BOOL ret;
2808 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2809 pDecodePara, pvStructInfo, pcbStructInfo);
2811 __TRY
2813 DWORD bytesNeeded;
2815 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2816 lpszStructType, pbEncoded, cbEncoded,
2817 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2819 if (!pvStructInfo)
2820 *pcbStructInfo = bytesNeeded;
2821 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2822 pvStructInfo, pcbStructInfo, bytesNeeded)))
2824 CRYPT_BIT_BLOB *blob;
2826 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2827 pvStructInfo = *(BYTE **)pvStructInfo;
2828 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2829 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2830 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2831 lpszStructType, pbEncoded, cbEncoded,
2832 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2833 &bytesNeeded);
2837 __EXCEPT_PAGE_FAULT
2839 SetLastError(STATUS_ACCESS_VIOLATION);
2840 ret = FALSE;
2842 __ENDTRY
2843 TRACE("returning %d (%08x)\n", ret, GetLastError());
2844 return ret;
2847 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2848 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2849 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2851 BOOL ret;
2853 if (!pvStructInfo)
2855 *pcbStructInfo = sizeof(int);
2856 return TRUE;
2858 __TRY
2860 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2861 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2862 DWORD size = sizeof(buf);
2864 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2865 if (pbEncoded[0] != ASN_INTEGER)
2867 SetLastError(CRYPT_E_ASN1_BADTAG);
2868 ret = FALSE;
2870 else
2871 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2872 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
2873 &size);
2874 if (ret)
2876 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2877 pvStructInfo, pcbStructInfo, sizeof(int))))
2879 int val, i;
2881 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2882 pvStructInfo = *(BYTE **)pvStructInfo;
2883 if (blob->pbData[blob->cbData - 1] & 0x80)
2885 /* initialize to a negative value to sign-extend */
2886 val = -1;
2888 else
2889 val = 0;
2890 for (i = 0; i < blob->cbData; i++)
2892 val <<= 8;
2893 val |= blob->pbData[blob->cbData - i - 1];
2895 memcpy(pvStructInfo, &val, sizeof(int));
2898 else if (GetLastError() == ERROR_MORE_DATA)
2899 SetLastError(CRYPT_E_ASN1_LARGE);
2901 __EXCEPT_PAGE_FAULT
2903 SetLastError(STATUS_ACCESS_VIOLATION);
2904 ret = FALSE;
2906 __ENDTRY
2907 return ret;
2910 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2911 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2912 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2914 BOOL ret;
2915 DWORD bytesNeeded, dataLen;
2917 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2919 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2921 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2922 if (!pvStructInfo)
2923 *pcbStructInfo = bytesNeeded;
2924 else if (*pcbStructInfo < bytesNeeded)
2926 *pcbStructInfo = bytesNeeded;
2927 SetLastError(ERROR_MORE_DATA);
2928 ret = FALSE;
2930 else
2932 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2934 blob->cbData = dataLen;
2935 assert(blob->pbData);
2936 if (blob->cbData)
2938 DWORD i;
2940 for (i = 0; i < blob->cbData; i++)
2942 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2943 dataLen - i - 1);
2948 return ret;
2951 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2952 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2953 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2955 BOOL ret;
2957 __TRY
2959 DWORD bytesNeeded;
2961 if (pbEncoded[0] != ASN_INTEGER)
2963 SetLastError(CRYPT_E_ASN1_BADTAG);
2964 ret = FALSE;
2966 else
2967 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2968 lpszStructType, pbEncoded, cbEncoded,
2969 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
2970 if (ret)
2972 if (!pvStructInfo)
2973 *pcbStructInfo = bytesNeeded;
2974 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2975 pvStructInfo, pcbStructInfo, bytesNeeded)))
2977 CRYPT_INTEGER_BLOB *blob;
2979 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2980 pvStructInfo = *(BYTE **)pvStructInfo;
2981 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2982 blob->pbData = (BYTE *)pvStructInfo +
2983 sizeof(CRYPT_INTEGER_BLOB);
2984 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2985 lpszStructType, pbEncoded, cbEncoded,
2986 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2987 &bytesNeeded);
2991 __EXCEPT_PAGE_FAULT
2993 SetLastError(STATUS_ACCESS_VIOLATION);
2994 ret = FALSE;
2996 __ENDTRY
2997 return ret;
3000 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
3001 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3002 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3003 void *pvStructInfo, DWORD *pcbStructInfo)
3005 BOOL ret;
3007 if (pbEncoded[0] == ASN_INTEGER)
3009 DWORD bytesNeeded, dataLen;
3011 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3013 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3015 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3016 if (!pvStructInfo)
3017 *pcbStructInfo = bytesNeeded;
3018 else if (*pcbStructInfo < bytesNeeded)
3020 *pcbStructInfo = bytesNeeded;
3021 SetLastError(ERROR_MORE_DATA);
3022 ret = FALSE;
3024 else
3026 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3028 blob->cbData = dataLen;
3029 assert(blob->pbData);
3030 /* remove leading zero byte if it exists */
3031 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3033 blob->cbData--;
3034 blob->pbData++;
3036 if (blob->cbData)
3038 DWORD i;
3040 for (i = 0; i < blob->cbData; i++)
3042 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3043 dataLen - i - 1);
3049 else
3051 SetLastError(CRYPT_E_ASN1_BADTAG);
3052 ret = FALSE;
3054 return ret;
3057 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3058 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3059 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3061 BOOL ret;
3063 __TRY
3065 DWORD bytesNeeded;
3067 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3068 lpszStructType, pbEncoded, cbEncoded,
3069 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
3071 if (!pvStructInfo)
3072 *pcbStructInfo = bytesNeeded;
3073 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3074 pvStructInfo, pcbStructInfo, bytesNeeded)))
3076 CRYPT_INTEGER_BLOB *blob;
3078 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3079 pvStructInfo = *(BYTE **)pvStructInfo;
3080 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3081 blob->pbData = (BYTE *)pvStructInfo +
3082 sizeof(CRYPT_INTEGER_BLOB);
3083 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3084 lpszStructType, pbEncoded, cbEncoded,
3085 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3086 &bytesNeeded);
3090 __EXCEPT_PAGE_FAULT
3092 SetLastError(STATUS_ACCESS_VIOLATION);
3093 ret = FALSE;
3095 __ENDTRY
3096 return ret;
3099 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3100 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3101 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3103 BOOL ret;
3105 if (!pvStructInfo)
3107 *pcbStructInfo = sizeof(int);
3108 return TRUE;
3110 __TRY
3112 if (pbEncoded[0] == ASN_ENUMERATED)
3114 unsigned int val = 0, i;
3116 if (cbEncoded <= 1)
3118 SetLastError(CRYPT_E_ASN1_EOD);
3119 ret = FALSE;
3121 else if (pbEncoded[1] == 0)
3123 SetLastError(CRYPT_E_ASN1_CORRUPT);
3124 ret = FALSE;
3126 else
3128 /* A little strange looking, but we have to accept a sign byte:
3129 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3130 * assuming a small length is okay here, it has to be in short
3131 * form.
3133 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3135 SetLastError(CRYPT_E_ASN1_LARGE);
3136 return FALSE;
3138 for (i = 0; i < pbEncoded[1]; i++)
3140 val <<= 8;
3141 val |= pbEncoded[2 + i];
3143 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3144 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3146 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3147 pvStructInfo = *(BYTE **)pvStructInfo;
3148 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3152 else
3154 SetLastError(CRYPT_E_ASN1_BADTAG);
3155 ret = FALSE;
3158 __EXCEPT_PAGE_FAULT
3160 SetLastError(STATUS_ACCESS_VIOLATION);
3161 ret = FALSE;
3163 __ENDTRY
3164 return ret;
3167 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3168 * if it fails.
3170 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3171 do { \
3172 BYTE i; \
3174 (word) = 0; \
3175 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3177 if (!isdigit(*(pbEncoded))) \
3179 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3180 ret = FALSE; \
3182 else \
3184 (word) *= 10; \
3185 (word) += *(pbEncoded)++ - '0'; \
3188 } while (0)
3190 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3191 SYSTEMTIME *sysTime)
3193 BOOL ret;
3195 __TRY
3197 ret = TRUE;
3198 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3200 WORD hours, minutes = 0;
3201 BYTE sign = *pbEncoded++;
3203 len--;
3204 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3205 if (ret && hours >= 24)
3207 SetLastError(CRYPT_E_ASN1_CORRUPT);
3208 ret = FALSE;
3210 else if (len >= 2)
3212 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3213 if (ret && minutes >= 60)
3215 SetLastError(CRYPT_E_ASN1_CORRUPT);
3216 ret = FALSE;
3219 if (ret)
3221 if (sign == '+')
3223 sysTime->wHour += hours;
3224 sysTime->wMinute += minutes;
3226 else
3228 if (hours > sysTime->wHour)
3230 sysTime->wDay--;
3231 sysTime->wHour = 24 - (hours - sysTime->wHour);
3233 else
3234 sysTime->wHour -= hours;
3235 if (minutes > sysTime->wMinute)
3237 sysTime->wHour--;
3238 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3240 else
3241 sysTime->wMinute -= minutes;
3246 __EXCEPT_PAGE_FAULT
3248 SetLastError(STATUS_ACCESS_VIOLATION);
3249 ret = FALSE;
3251 __ENDTRY
3252 return ret;
3255 #define MIN_ENCODED_TIME_LENGTH 10
3257 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3258 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3259 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3261 BOOL ret;
3263 if (!pvStructInfo)
3265 *pcbStructInfo = sizeof(FILETIME);
3266 return TRUE;
3268 __TRY
3270 ret = TRUE;
3271 if (pbEncoded[0] == ASN_UTCTIME)
3273 if (cbEncoded <= 1)
3275 SetLastError(CRYPT_E_ASN1_EOD);
3276 ret = FALSE;
3278 else if (pbEncoded[1] > 0x7f)
3280 /* long-form date strings really can't be valid */
3281 SetLastError(CRYPT_E_ASN1_CORRUPT);
3282 ret = FALSE;
3284 else
3286 SYSTEMTIME sysTime = { 0 };
3287 BYTE len = pbEncoded[1];
3289 if (len < MIN_ENCODED_TIME_LENGTH)
3291 SetLastError(CRYPT_E_ASN1_CORRUPT);
3292 ret = FALSE;
3294 else
3296 pbEncoded += 2;
3297 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3298 if (sysTime.wYear >= 50)
3299 sysTime.wYear += 1900;
3300 else
3301 sysTime.wYear += 2000;
3302 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3303 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3304 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3305 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3306 if (ret && len > 0)
3308 if (len >= 2 && isdigit(*pbEncoded) &&
3309 isdigit(*(pbEncoded + 1)))
3310 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3311 sysTime.wSecond);
3312 else if (isdigit(*pbEncoded))
3313 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3314 sysTime.wSecond);
3315 if (ret)
3316 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3317 &sysTime);
3319 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3320 pDecodePara, pvStructInfo, pcbStructInfo,
3321 sizeof(FILETIME))))
3323 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3324 pvStructInfo = *(BYTE **)pvStructInfo;
3325 ret = SystemTimeToFileTime(&sysTime,
3326 (FILETIME *)pvStructInfo);
3331 else
3333 SetLastError(CRYPT_E_ASN1_BADTAG);
3334 ret = FALSE;
3337 __EXCEPT_PAGE_FAULT
3339 SetLastError(STATUS_ACCESS_VIOLATION);
3340 ret = FALSE;
3342 __ENDTRY
3343 return ret;
3346 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3347 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3348 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3350 BOOL ret;
3352 if (!pvStructInfo)
3354 *pcbStructInfo = sizeof(FILETIME);
3355 return TRUE;
3357 __TRY
3359 ret = TRUE;
3360 if (pbEncoded[0] == ASN_GENERALTIME)
3362 if (cbEncoded <= 1)
3364 SetLastError(CRYPT_E_ASN1_EOD);
3365 ret = FALSE;
3367 else if (pbEncoded[1] > 0x7f)
3369 /* long-form date strings really can't be valid */
3370 SetLastError(CRYPT_E_ASN1_CORRUPT);
3371 ret = FALSE;
3373 else
3375 BYTE len = pbEncoded[1];
3377 if (len < MIN_ENCODED_TIME_LENGTH)
3379 SetLastError(CRYPT_E_ASN1_CORRUPT);
3380 ret = FALSE;
3382 else
3384 SYSTEMTIME sysTime = { 0 };
3386 pbEncoded += 2;
3387 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3388 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3389 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3390 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3391 if (ret && len > 0)
3393 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3394 sysTime.wMinute);
3395 if (ret && len > 0)
3396 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3397 sysTime.wSecond);
3398 if (ret && len > 0 && (*pbEncoded == '.' ||
3399 *pbEncoded == ','))
3401 BYTE digits;
3403 pbEncoded++;
3404 len--;
3405 /* workaround macro weirdness */
3406 digits = min(len, 3);
3407 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3408 sysTime.wMilliseconds);
3410 if (ret)
3411 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3412 &sysTime);
3414 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3415 pDecodePara, pvStructInfo, pcbStructInfo,
3416 sizeof(FILETIME))))
3418 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3419 pvStructInfo = *(BYTE **)pvStructInfo;
3420 ret = SystemTimeToFileTime(&sysTime,
3421 (FILETIME *)pvStructInfo);
3426 else
3428 SetLastError(CRYPT_E_ASN1_BADTAG);
3429 ret = FALSE;
3432 __EXCEPT_PAGE_FAULT
3434 SetLastError(STATUS_ACCESS_VIOLATION);
3435 ret = FALSE;
3437 __ENDTRY
3438 return ret;
3441 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3442 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3443 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3445 BOOL ret;
3447 __TRY
3449 if (pbEncoded[0] == ASN_UTCTIME)
3450 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3451 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3452 pcbStructInfo);
3453 else if (pbEncoded[0] == ASN_GENERALTIME)
3454 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3455 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3456 pvStructInfo, pcbStructInfo);
3457 else
3459 SetLastError(CRYPT_E_ASN1_BADTAG);
3460 ret = FALSE;
3463 __EXCEPT_PAGE_FAULT
3465 SetLastError(STATUS_ACCESS_VIOLATION);
3466 ret = FALSE;
3468 __ENDTRY
3469 return ret;
3472 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3473 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3474 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3476 BOOL ret = TRUE;
3478 __TRY
3480 if (pbEncoded[0] == ASN_SEQUENCEOF)
3482 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3484 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3486 BYTE lenBytes;
3487 const BYTE *ptr;
3489 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3490 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3491 cValue = 0;
3492 ptr = pbEncoded + 1 + lenBytes;
3493 remainingLen = dataLen;
3494 while (ret && remainingLen)
3496 DWORD nextLen;
3498 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3499 if (ret)
3501 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3503 remainingLen -= 1 + nextLenBytes + nextLen;
3504 ptr += 1 + nextLenBytes + nextLen;
3505 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3506 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3507 bytesNeeded += 1 + nextLenBytes + nextLen;
3508 cValue++;
3511 if (ret)
3513 CRYPT_SEQUENCE_OF_ANY *seq;
3514 BYTE *nextPtr;
3515 DWORD i;
3517 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3518 pvStructInfo, pcbStructInfo, bytesNeeded)))
3520 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3521 pvStructInfo = *(BYTE **)pvStructInfo;
3522 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3523 seq->cValue = cValue;
3524 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3525 sizeof(*seq));
3526 nextPtr = (BYTE *)seq->rgValue +
3527 cValue * sizeof(CRYPT_DER_BLOB);
3528 ptr = pbEncoded + 1 + lenBytes;
3529 remainingLen = dataLen;
3530 i = 0;
3531 while (ret && remainingLen)
3533 DWORD nextLen;
3535 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3536 if (ret)
3538 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3540 seq->rgValue[i].cbData = 1 + nextLenBytes +
3541 nextLen;
3542 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3543 seq->rgValue[i].pbData = (BYTE *)ptr;
3544 else
3546 seq->rgValue[i].pbData = nextPtr;
3547 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3548 nextLen);
3549 nextPtr += 1 + nextLenBytes + nextLen;
3551 remainingLen -= 1 + nextLenBytes + nextLen;
3552 ptr += 1 + nextLenBytes + nextLen;
3553 i++;
3560 else
3562 SetLastError(CRYPT_E_ASN1_BADTAG);
3563 ret = FALSE;
3566 __EXCEPT_PAGE_FAULT
3568 SetLastError(STATUS_ACCESS_VIOLATION);
3569 ret = FALSE;
3571 __ENDTRY
3572 return ret;
3575 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3576 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3577 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3579 BOOL ret;
3581 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3583 DWORD bytesNeeded, dataLen;
3585 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3587 struct AsnArrayDescriptor arrayDesc = {
3588 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3589 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3590 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3591 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3593 if (dataLen)
3595 DWORD nameLen;
3597 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3598 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3599 0, NULL, NULL, &nameLen, NULL);
3600 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3602 else
3603 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3604 if (!pvStructInfo)
3605 *pcbStructInfo = bytesNeeded;
3606 else if (*pcbStructInfo < bytesNeeded)
3608 *pcbStructInfo = bytesNeeded;
3609 SetLastError(ERROR_MORE_DATA);
3610 ret = FALSE;
3612 else
3614 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3616 if (dataLen)
3618 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3619 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3620 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3621 0, NULL, &name->u.FullName, pcbStructInfo,
3622 name->u.FullName.rgAltEntry);
3624 else
3625 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3629 else
3631 SetLastError(CRYPT_E_ASN1_BADTAG);
3632 ret = FALSE;
3634 return ret;
3637 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3638 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3639 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3641 struct AsnDecodeSequenceItem items[] = {
3642 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3643 DistPointName), CRYPT_AsnDecodeDistPointName,
3644 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3645 DistPointName.u.FullName.rgAltEntry), 0 },
3646 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3647 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3648 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3649 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3650 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3651 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3653 BOOL ret;
3655 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3656 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3657 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3658 return ret;
3661 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3662 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3663 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3665 BOOL ret;
3667 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3668 pDecodePara, pvStructInfo, *pcbStructInfo);
3670 __TRY
3672 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3673 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3674 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3676 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3677 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3679 __EXCEPT_PAGE_FAULT
3681 SetLastError(STATUS_ACCESS_VIOLATION);
3682 ret = FALSE;
3684 __ENDTRY
3685 return ret;
3688 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3689 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3690 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3692 BOOL ret;
3694 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3695 pDecodePara, pvStructInfo, *pcbStructInfo);
3697 __TRY
3699 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3700 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3702 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3703 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3705 __EXCEPT_PAGE_FAULT
3707 SetLastError(STATUS_ACCESS_VIOLATION);
3708 ret = FALSE;
3710 __ENDTRY
3711 return ret;
3714 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3715 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3716 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3718 BOOL ret;
3720 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3721 pDecodePara, pvStructInfo, *pcbStructInfo);
3723 __TRY
3725 struct AsnDecodeSequenceItem items[] = {
3726 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3727 DistPointName), CRYPT_AsnDecodeDistPointName,
3728 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3729 offsetof(CRL_ISSUING_DIST_POINT,
3730 DistPointName.u.FullName.rgAltEntry), 0 },
3731 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3732 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3733 FALSE, 0 },
3734 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3735 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3736 FALSE, 0 },
3737 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3738 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3739 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3740 OnlySomeReasonFlags.pbData), 0 },
3741 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3742 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3745 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3746 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3747 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3749 __EXCEPT_PAGE_FAULT
3751 SetLastError(STATUS_ACCESS_VIOLATION);
3752 ret = FALSE;
3754 __ENDTRY
3755 return ret;
3758 static BOOL WINAPI CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType,
3759 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3760 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3762 BOOL ret;
3763 struct AsnDecodeSequenceItem items[] = {
3764 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
3765 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
3766 Issuer.pbData) },
3767 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
3768 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
3769 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
3771 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3772 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3774 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3775 pDecodePara, pvStructInfo, *pcbStructInfo);
3777 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3778 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3779 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
3780 issuerSerial ? issuerSerial->Issuer.pbData : NULL);
3781 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
3783 SetLastError(CRYPT_E_ASN1_CORRUPT);
3784 ret = FALSE;
3786 TRACE("returning %d\n", ret);
3787 return ret;
3790 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
3791 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3792 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3794 BOOL ret = FALSE;
3796 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3797 pDecodePara, pvStructInfo, *pcbStructInfo);
3799 __TRY
3801 struct AsnDecodeSequenceItem items[] = {
3802 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
3803 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3804 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
3805 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
3806 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
3807 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
3808 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3809 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
3810 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
3811 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3812 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
3813 HashEncryptionAlgorithm.pszObjId), 0 },
3814 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CMSG_SIGNER_INFO, AuthAttrs),
3815 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3816 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
3817 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
3818 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3819 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
3820 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
3821 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
3822 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
3825 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3826 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3827 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3829 __EXCEPT_PAGE_FAULT
3831 SetLastError(STATUS_ACCESS_VIOLATION);
3833 __ENDTRY
3834 TRACE("returning %d\n", ret);
3835 return ret;
3838 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3839 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3840 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3842 static HCRYPTOIDFUNCSET set = NULL;
3843 BOOL ret = FALSE;
3844 CryptDecodeObjectExFunc decodeFunc = NULL;
3845 HCRYPTOIDFUNCADDR hFunc = NULL;
3847 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
3848 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
3849 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3851 if (!pvStructInfo && !pcbStructInfo)
3853 SetLastError(ERROR_INVALID_PARAMETER);
3854 return FALSE;
3856 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3857 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3859 SetLastError(ERROR_FILE_NOT_FOUND);
3860 return FALSE;
3862 if (!cbEncoded)
3864 SetLastError(CRYPT_E_ASN1_EOD);
3865 return FALSE;
3867 if (cbEncoded > MAX_ENCODED_LEN)
3869 SetLastError(CRYPT_E_ASN1_LARGE);
3870 return FALSE;
3873 SetLastError(NOERROR);
3874 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3875 *(BYTE **)pvStructInfo = NULL;
3876 if (!HIWORD(lpszStructType))
3878 switch (LOWORD(lpszStructType))
3880 case (WORD)X509_CERT:
3881 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3882 break;
3883 case (WORD)X509_CERT_TO_BE_SIGNED:
3884 decodeFunc = CRYPT_AsnDecodeCert;
3885 break;
3886 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3887 decodeFunc = CRYPT_AsnDecodeCRL;
3888 break;
3889 case (WORD)X509_EXTENSIONS:
3890 decodeFunc = CRYPT_AsnDecodeExtensions;
3891 break;
3892 case (WORD)X509_NAME_VALUE:
3893 decodeFunc = CRYPT_AsnDecodeNameValue;
3894 break;
3895 case (WORD)X509_NAME:
3896 decodeFunc = CRYPT_AsnDecodeName;
3897 break;
3898 case (WORD)X509_PUBLIC_KEY_INFO:
3899 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
3900 break;
3901 case (WORD)X509_AUTHORITY_KEY_ID:
3902 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3903 break;
3904 case (WORD)X509_ALTERNATE_NAME:
3905 decodeFunc = CRYPT_AsnDecodeAltName;
3906 break;
3907 case (WORD)X509_BASIC_CONSTRAINTS:
3908 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3909 break;
3910 case (WORD)X509_BASIC_CONSTRAINTS2:
3911 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3912 break;
3913 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3914 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3915 break;
3916 case (WORD)X509_UNICODE_NAME:
3917 decodeFunc = CRYPT_AsnDecodeUnicodeName;
3918 break;
3919 case (WORD)PKCS_ATTRIBUTE:
3920 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
3921 break;
3922 case (WORD)X509_UNICODE_NAME_VALUE:
3923 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
3924 break;
3925 case (WORD)X509_OCTET_STRING:
3926 decodeFunc = CRYPT_AsnDecodeOctets;
3927 break;
3928 case (WORD)X509_BITS:
3929 case (WORD)X509_KEY_USAGE:
3930 decodeFunc = CRYPT_AsnDecodeBits;
3931 break;
3932 case (WORD)X509_INTEGER:
3933 decodeFunc = CRYPT_AsnDecodeInt;
3934 break;
3935 case (WORD)X509_MULTI_BYTE_INTEGER:
3936 decodeFunc = CRYPT_AsnDecodeInteger;
3937 break;
3938 case (WORD)X509_MULTI_BYTE_UINT:
3939 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3940 break;
3941 case (WORD)X509_ENUMERATED:
3942 decodeFunc = CRYPT_AsnDecodeEnumerated;
3943 break;
3944 case (WORD)X509_CHOICE_OF_TIME:
3945 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3946 break;
3947 case (WORD)X509_AUTHORITY_KEY_ID2:
3948 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
3949 break;
3950 case (WORD)PKCS_CONTENT_INFO:
3951 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
3952 break;
3953 case (WORD)X509_SEQUENCE_OF_ANY:
3954 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3955 break;
3956 case (WORD)PKCS_UTC_TIME:
3957 decodeFunc = CRYPT_AsnDecodeUtcTime;
3958 break;
3959 case (WORD)X509_CRL_DIST_POINTS:
3960 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3961 break;
3962 case (WORD)X509_ENHANCED_KEY_USAGE:
3963 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3964 break;
3965 case (WORD)PKCS_ATTRIBUTES:
3966 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
3967 break;
3968 case (WORD)X509_ISSUING_DIST_POINT:
3969 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3970 break;
3971 case (WORD)PKCS7_SIGNER_INFO:
3972 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
3973 break;
3974 default:
3975 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3978 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3979 decodeFunc = CRYPT_AsnDecodeExtensions;
3980 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3981 decodeFunc = CRYPT_AsnDecodeUtcTime;
3982 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3983 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3984 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
3985 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
3986 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3987 decodeFunc = CRYPT_AsnDecodeEnumerated;
3988 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3989 decodeFunc = CRYPT_AsnDecodeBits;
3990 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3991 decodeFunc = CRYPT_AsnDecodeOctets;
3992 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3993 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3994 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3995 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3996 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3997 decodeFunc = CRYPT_AsnDecodeAltName;
3998 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3999 decodeFunc = CRYPT_AsnDecodeAltName;
4000 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4001 decodeFunc = CRYPT_AsnDecodeAltName;
4002 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4003 decodeFunc = CRYPT_AsnDecodeAltName;
4004 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4005 decodeFunc = CRYPT_AsnDecodeAltName;
4006 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4007 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4008 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4009 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4010 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4011 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4012 else
4013 TRACE("OID %s not found or unimplemented, looking for DLL\n",
4014 debugstr_a(lpszStructType));
4015 if (!decodeFunc)
4017 if (!set)
4018 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4019 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4020 (void **)&decodeFunc, &hFunc);
4022 if (decodeFunc)
4023 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4024 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4025 else
4026 SetLastError(ERROR_FILE_NOT_FOUND);
4027 if (hFunc)
4028 CryptFreeOIDFunctionAddress(hFunc, 0);
4029 return ret;