- Sync up Mm interface with WinLdr branch (introduce the concept of a memory type...
[reactos.git] / reactos / dll / win32 / crypt32 / decode.c
1 /*
2 * Copyright 2005 Juan Lang
3 *
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.
8 *
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.
13 *
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
17 *
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.
22 *
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.)
27 *
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
29 *
30 * MSDN, especially:
31 * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
32 */
33
34 #include <assert.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38
39 #define NONAMELESSUNION
40
41 #include "windef.h"
42 #include "winbase.h"
43 #include "excpt.h"
44 #include "wincrypt.h"
45 #include "winnls.h"
46 #include "winreg.h"
47 #include "snmp.h"
48 #include "wine/debug.h"
49 #include "wine/exception.h"
50 #include "crypt32_private.h"
51
52 /* This is a bit arbitrary, but to set some limit: */
53 #define MAX_ENCODED_LEN 0x02000000
54
55 #define ASN_FLAGS_MASK 0xe0
56 #define ASN_TYPE_MASK 0x1f
57
58 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
59
60 struct GenericArray
61 {
62 DWORD cItems;
63 BYTE *rgItems;
64 };
65
66 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
67 DWORD, DWORD, void *, DWORD *);
68 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
69 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
70
71 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
72 * The dwCertEncodingType and lpszStructType are ignored by the built-in
73 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
74 * since it must call functions in external DLLs that follow these signatures.
75 */
76 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
77 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
78 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
79 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
80 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
81 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
82 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
83 * time, doesn't do memory allocation, and doesn't do exception handling.
84 * (This isn't intended to be the externally-called one.)
85 */
86 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
87 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
88 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
89 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
90 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
92 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
93 /* Internal function */
94 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
95 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
96 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
97 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
98 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
99 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
100 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
101 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
102 * member has been initialized, doesn't do exception handling, and doesn't do
103 * memory allocation.
104 */
105 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
106 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
107 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
108 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
109 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
110 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
111 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
112 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
113 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
114 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
115 * member has been initialized, doesn't do exception handling, and doesn't do
116 * memory allocation. Also doesn't check tag, assumes the caller has checked
117 * it.
118 */
119 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
120 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
121 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
122 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
123 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
124 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
125 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
126 void *pvStructInfo, DWORD *pcbStructInfo);
127
128 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
129 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
130 DWORD *pcbStructInfo)
131 {
132 static HCRYPTOIDFUNCSET set = NULL;
133 BOOL ret = FALSE;
134 CryptDecodeObjectFunc pCryptDecodeObject;
135 HCRYPTOIDFUNCADDR hFunc;
136
137 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
138 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
139 pvStructInfo, pcbStructInfo);
140
141 if (!pvStructInfo && !pcbStructInfo)
142 {
143 SetLastError(ERROR_INVALID_PARAMETER);
144 return FALSE;
145 }
146
147 /* Try registered DLL first.. */
148 if (!set)
149 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
150 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
151 (void **)&pCryptDecodeObject, &hFunc);
152 if (pCryptDecodeObject)
153 {
154 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
155 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
156 CryptFreeOIDFunctionAddress(hFunc, 0);
157 }
158 else
159 {
160 /* If not, use CryptDecodeObjectEx */
161 ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
162 cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
163 }
164 return ret;
165 }
166
167 /* Gets the number of length bytes from the given (leading) length byte */
168 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
169
170 /* Helper function to get the encoded length of the data starting at pbEncoded,
171 * where pbEncoded[0] is the tag. If the data are too short to contain a
172 * length or if the length is too large for cbEncoded, sets an appropriate
173 * error code and returns FALSE.
174 */
175 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
176 DWORD *len)
177 {
178 BOOL ret;
179
180 if (cbEncoded <= 1)
181 {
182 SetLastError(CRYPT_E_ASN1_CORRUPT);
183 ret = FALSE;
184 }
185 else if (pbEncoded[1] <= 0x7f)
186 {
187 if (pbEncoded[1] + 1 > cbEncoded)
188 {
189 SetLastError(CRYPT_E_ASN1_EOD);
190 ret = FALSE;
191 }
192 else
193 {
194 *len = pbEncoded[1];
195 ret = TRUE;
196 }
197 }
198 else
199 {
200 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
201
202 if (lenLen > sizeof(DWORD) + 1)
203 {
204 SetLastError(CRYPT_E_ASN1_LARGE);
205 ret = FALSE;
206 }
207 else if (lenLen + 2 > cbEncoded)
208 {
209 SetLastError(CRYPT_E_ASN1_CORRUPT);
210 ret = FALSE;
211 }
212 else
213 {
214 DWORD out = 0;
215
216 pbEncoded += 2;
217 while (--lenLen)
218 {
219 out <<= 8;
220 out |= *pbEncoded++;
221 }
222 if (out + lenLen + 1 > cbEncoded)
223 {
224 SetLastError(CRYPT_E_ASN1_EOD);
225 ret = FALSE;
226 }
227 else
228 {
229 *len = out;
230 ret = TRUE;
231 }
232 }
233 }
234 return ret;
235 }
236
237 /* Helper function to check *pcbStructInfo, set it to the required size, and
238 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
239 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
240 * pointer to the newly allocated memory.
241 */
242 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
243 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
244 DWORD bytesNeeded)
245 {
246 BOOL ret = TRUE;
247
248 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
249 {
250 if (pDecodePara && pDecodePara->pfnAlloc)
251 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
252 else
253 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
254 if (!*(BYTE **)pvStructInfo)
255 ret = FALSE;
256 else
257 *pcbStructInfo = bytesNeeded;
258 }
259 else if (*pcbStructInfo < bytesNeeded)
260 {
261 *pcbStructInfo = bytesNeeded;
262 SetLastError(ERROR_MORE_DATA);
263 ret = FALSE;
264 }
265 return ret;
266 }
267
268 /* tag:
269 * The expected tag of the item. If tag is 0, decodeFunc is called
270 * regardless of the tag value seen.
271 * offset:
272 * A sequence is decoded into a struct. The offset member is the
273 * offset of this item within that struct.
274 * decodeFunc:
275 * The decoder function to use. If this is NULL, then the member isn't
276 * decoded, but minSize space is reserved for it.
277 * minSize:
278 * The minimum amount of space occupied after decoding. You must set this.
279 * optional:
280 * If true, and the tag doesn't match the expected tag for this item,
281 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
282 * filled with 0 for this member.
283 * hasPointer, pointerOffset, minSize:
284 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
285 * the offset within the (outer) struct of the data pointer (or to the
286 * first data pointer, if more than one exist).
287 * size:
288 * Used by CRYPT_AsnDecodeSequence, not for your use.
289 */
290 struct AsnDecodeSequenceItem
291 {
292 BYTE tag;
293 DWORD offset;
294 CryptDecodeObjectExFunc decodeFunc;
295 DWORD minSize;
296 BOOL optional;
297 BOOL hasPointer;
298 DWORD pointerOffset;
299 DWORD size;
300 };
301
302 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
303 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
304 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData)
305 {
306 BOOL ret;
307 DWORD i;
308 const BYTE *ptr;
309
310 ptr = pbEncoded + 1 + GET_LEN_BYTES(pbEncoded[1]);
311 for (i = 0, ret = TRUE; ret && i < cItem; i++)
312 {
313 if (cbEncoded - (ptr - pbEncoded) != 0)
314 {
315 DWORD nextItemLen;
316
317 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
318 &nextItemLen)))
319 {
320 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
321
322 if (ptr[0] == items[i].tag || !items[i].tag)
323 {
324 if (nextData && pvStructInfo && items[i].hasPointer)
325 {
326 TRACE("Setting next pointer to %p\n",
327 nextData);
328 *(BYTE **)((BYTE *)pvStructInfo +
329 items[i].pointerOffset) = nextData;
330 }
331 if (items[i].decodeFunc)
332 {
333 if (pvStructInfo)
334 TRACE("decoding item %d\n", i);
335 else
336 TRACE("sizing item %d\n", i);
337 ret = items[i].decodeFunc(dwCertEncodingType,
338 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
339 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
340 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
341 : NULL, &items[i].size);
342 if (ret)
343 {
344 if (nextData && items[i].hasPointer &&
345 items[i].size > items[i].minSize)
346 {
347 nextData += items[i].size - items[i].minSize;
348 /* align nextData to DWORD boundaries */
349 if (items[i].size % sizeof(DWORD))
350 nextData += sizeof(DWORD) - items[i].size %
351 sizeof(DWORD);
352 }
353 /* Account for alignment padding */
354 if (items[i].size % sizeof(DWORD))
355 items[i].size += sizeof(DWORD) -
356 items[i].size % sizeof(DWORD);
357 ptr += 1 + nextItemLenBytes + nextItemLen;
358 }
359 else if (items[i].optional &&
360 GetLastError() == CRYPT_E_ASN1_BADTAG)
361 {
362 TRACE("skipping optional item %d\n", i);
363 items[i].size = items[i].minSize;
364 SetLastError(NOERROR);
365 ret = TRUE;
366 }
367 else
368 TRACE("item %d failed: %08x\n", i,
369 GetLastError());
370 }
371 else
372 items[i].size = items[i].minSize;
373 }
374 else if (items[i].optional)
375 {
376 TRACE("skipping optional item %d\n", i);
377 items[i].size = items[i].minSize;
378 }
379 else
380 {
381 TRACE("tag %02x doesn't match expected %02x\n",
382 ptr[0], items[i].tag);
383 SetLastError(CRYPT_E_ASN1_BADTAG);
384 ret = FALSE;
385 }
386 }
387 }
388 else if (items[i].optional)
389 {
390 TRACE("missing optional item %d, skipping\n", i);
391 items[i].size = items[i].minSize;
392 }
393 else
394 {
395 TRACE("not enough bytes for item %d, failing\n", i);
396 SetLastError(CRYPT_E_ASN1_CORRUPT);
397 ret = FALSE;
398 }
399 }
400 if (cbEncoded - (ptr - pbEncoded) != 0)
401 {
402 TRACE("%d remaining bytes, failing\n", cbEncoded -
403 (ptr - pbEncoded));
404 SetLastError(CRYPT_E_ASN1_CORRUPT);
405 ret = FALSE;
406 }
407 return ret;
408 }
409
410 /* This decodes an arbitrary sequence into a contiguous block of memory
411 * (basically, a struct.) Each element being decoded is described by a struct
412 * AsnDecodeSequenceItem, see above.
413 * startingPointer is an optional pointer to the first place where dynamic
414 * data will be stored. If you know the starting offset, you may pass it
415 * here. Otherwise, pass NULL, and one will be inferred from the items.
416 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
417 * If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
418 */
419 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
420 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
421 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
422 void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
423 {
424 BOOL ret;
425
426 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
427 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
428 startingPointer);
429
430 if (pbEncoded[0] == ASN_SEQUENCE)
431 {
432 DWORD dataLen;
433
434 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
435 {
436 DWORD i;
437
438 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
439 cbEncoded, dwFlags, NULL, NULL);
440 if (ret)
441 {
442 DWORD bytesNeeded = 0, structSize = 0;
443
444 for (i = 0; i < cItem; i++)
445 {
446 bytesNeeded += items[i].size;
447 structSize += items[i].minSize;
448 }
449 if (!pvStructInfo)
450 *pcbStructInfo = bytesNeeded;
451 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
452 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
453 {
454 BYTE *nextData;
455
456 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
457 pvStructInfo = *(BYTE **)pvStructInfo;
458 if (startingPointer)
459 nextData = (BYTE *)startingPointer;
460 else
461 nextData = (BYTE *)pvStructInfo + structSize;
462 memset(pvStructInfo, 0, structSize);
463 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
464 pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
465 }
466 }
467 }
468 }
469 else
470 {
471 SetLastError(CRYPT_E_ASN1_BADTAG);
472 ret = FALSE;
473 }
474 TRACE("returning %d (%08x)\n", ret, GetLastError());
475 return ret;
476 }
477
478 /* tag:
479 * The expected tag of the entire encoded array (usually a variant
480 * of ASN_SETOF or ASN_SEQUENCEOF.)
481 * decodeFunc:
482 * used to decode each item in the array
483 * itemSize:
484 * is the minimum size of each decoded item
485 * hasPointer:
486 * indicates whether each item has a dynamic pointer
487 * pointerOffset:
488 * indicates the offset within itemSize at which the pointer exists
489 */
490 struct AsnArrayDescriptor
491 {
492 BYTE tag;
493 CryptDecodeObjectExFunc decodeFunc;
494 DWORD itemSize;
495 BOOL hasPointer;
496 DWORD pointerOffset;
497 };
498
499 struct AsnArrayItemSize
500 {
501 DWORD encodedLen;
502 DWORD size;
503 };
504
505 /* Decodes an array of like types into a struct GenericArray.
506 * The layout and decoding of the array are described by a struct
507 * AsnArrayDescriptor.
508 */
509 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
510 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
511 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
512 void *startingPointer)
513 {
514 BOOL ret = TRUE;
515
516 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
517 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
518 startingPointer);
519
520 if (pbEncoded[0] == arrayDesc->tag)
521 {
522 DWORD dataLen;
523
524 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
525 {
526 DWORD bytesNeeded, cItems = 0;
527 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
528 /* There can be arbitrarily many items, but there is often only one.
529 */
530 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
531
532 bytesNeeded = sizeof(struct GenericArray);
533 if (dataLen)
534 {
535 const BYTE *ptr;
536
537 for (ptr = pbEncoded + 1 + lenBytes; ret &&
538 ptr - pbEncoded - 1 - lenBytes < dataLen; )
539 {
540 DWORD itemLenBytes, itemDataLen, size;
541
542 itemLenBytes = GET_LEN_BYTES(ptr[1]);
543 /* Each item decoded may not tolerate extraneous bytes, so
544 * get the length of the next element and pass it directly.
545 */
546 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
547 &itemDataLen);
548 if (ret)
549 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
550 1 + itemLenBytes + itemDataLen,
551 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
552 &size);
553 if (ret)
554 {
555 DWORD nextLen;
556
557 cItems++;
558 if (itemSizes != &itemSize)
559 itemSizes = CryptMemRealloc(itemSizes,
560 cItems * sizeof(struct AsnArrayItemSize));
561 else
562 {
563 itemSizes =
564 CryptMemAlloc(
565 cItems * sizeof(struct AsnArrayItemSize));
566 if (itemSizes)
567 memcpy(itemSizes, &itemSize, sizeof(itemSize));
568 }
569 if (itemSizes)
570 {
571 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
572 + itemDataLen;
573 itemSizes[cItems - 1].size = size;
574 bytesNeeded += size;
575 ret = CRYPT_GetLen(ptr,
576 cbEncoded - (ptr - pbEncoded), &nextLen);
577 if (ret)
578 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
579 }
580 else
581 ret = FALSE;
582 }
583 }
584 }
585 if (ret)
586 {
587 if (!pvStructInfo)
588 *pcbStructInfo = bytesNeeded;
589 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
590 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
591 {
592 DWORD i;
593 BYTE *nextData;
594 const BYTE *ptr;
595 struct GenericArray *array;
596
597 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
598 pvStructInfo = *(BYTE **)pvStructInfo;
599 array = (struct GenericArray *)pvStructInfo;
600 array->cItems = cItems;
601 if (startingPointer)
602 array->rgItems = startingPointer;
603 else
604 array->rgItems = (BYTE *)array +
605 sizeof(struct GenericArray);
606 nextData = (BYTE *)array->rgItems +
607 array->cItems * arrayDesc->itemSize;
608 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
609 i < cItems && ptr - pbEncoded - 1 - lenBytes <
610 dataLen; i++)
611 {
612 if (arrayDesc->hasPointer)
613 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
614 + arrayDesc->pointerOffset) = nextData;
615 ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
616 itemSizes[i].encodedLen,
617 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
618 array->rgItems + i * arrayDesc->itemSize,
619 &itemSizes[i].size);
620 if (ret)
621 {
622 DWORD nextLen;
623
624 nextData += itemSizes[i].size - arrayDesc->itemSize;
625 ret = CRYPT_GetLen(ptr,
626 cbEncoded - (ptr - pbEncoded), &nextLen);
627 if (ret)
628 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
629 }
630 }
631 }
632 }
633 if (itemSizes != &itemSize)
634 CryptMemFree(itemSizes);
635 }
636 }
637 else
638 {
639 SetLastError(CRYPT_E_ASN1_BADTAG);
640 ret = FALSE;
641 }
642 return ret;
643 }
644
645 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
646 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
647 * to CRYPT_E_ASN1_CORRUPT.
648 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
649 * set!
650 */
651 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
652 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
653 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
654 {
655 BOOL ret;
656 DWORD dataLen;
657
658 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
659 {
660 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
661 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
662
663 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
664 bytesNeeded += 1 + lenBytes + dataLen;
665
666 if (!pvStructInfo)
667 *pcbStructInfo = bytesNeeded;
668 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
669 pvStructInfo, pcbStructInfo, bytesNeeded)))
670 {
671 CRYPT_DER_BLOB *blob;
672
673 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
674 pvStructInfo = *(BYTE **)pvStructInfo;
675 blob = (CRYPT_DER_BLOB *)pvStructInfo;
676 blob->cbData = 1 + lenBytes + dataLen;
677 if (blob->cbData)
678 {
679 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
680 blob->pbData = (BYTE *)pbEncoded;
681 else
682 {
683 assert(blob->pbData);
684 memcpy(blob->pbData, pbEncoded, blob->cbData);
685 }
686 }
687 else
688 {
689 SetLastError(CRYPT_E_ASN1_CORRUPT);
690 ret = FALSE;
691 }
692 }
693 }
694 return ret;
695 }
696
697 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
698 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
699 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
700 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
701 {
702 BOOL ret;
703
704 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
705 pDecodePara, pvStructInfo, *pcbStructInfo);
706
707 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
708 * place.
709 */
710 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
711 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
712 pvStructInfo, pcbStructInfo);
713 if (ret && pvStructInfo)
714 {
715 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
716
717 if (blob->cbData)
718 {
719 DWORD i;
720 BYTE temp;
721
722 for (i = 0; i < blob->cbData / 2; i++)
723 {
724 temp = blob->pbData[i];
725 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
726 blob->pbData[blob->cbData - i - 1] = temp;
727 }
728 }
729 }
730 TRACE("returning %d (%08x)\n", ret, GetLastError());
731 return ret;
732 }
733
734 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
735 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
736 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
737 {
738 BOOL ret = TRUE;
739
740 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
741 pDecodePara, pvStructInfo, *pcbStructInfo);
742
743 __TRY
744 {
745 struct AsnDecodeSequenceItem items[] = {
746 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
747 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
748 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
749 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
750 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
751 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
752 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
753 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
754 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
755 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
756 };
757
758 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
759 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
760 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
761 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
762 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
763 }
764 __EXCEPT_PAGE_FAULT
765 {
766 SetLastError(STATUS_ACCESS_VIOLATION);
767 ret = FALSE;
768 }
769 __ENDTRY
770
771 TRACE("Returning %d (%08x)\n", ret, GetLastError());
772 return ret;
773 }
774
775 /* Internal function */
776 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
777 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
778 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
779 {
780 BOOL ret;
781 DWORD dataLen;
782
783 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
784 {
785 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
786
787 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
788 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
789 pvStructInfo, pcbStructInfo);
790 }
791 return ret;
792 }
793
794 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
795 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
796 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
797 {
798 BOOL ret;
799
800 struct AsnDecodeSequenceItem items[] = {
801 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
802 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
803 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
804 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
805 };
806
807 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
808 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
809 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
810 return ret;
811 }
812
813 /* Internal function */
814 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
815 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
816 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
817 {
818 BOOL ret;
819 DWORD dataLen;
820
821 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
822 {
823 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
824
825 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
826 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
827 pDecodePara, pvStructInfo, pcbStructInfo);
828 }
829 return ret;
830 }
831
832 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
833 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
834 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
835 {
836 BOOL ret = TRUE;
837 struct AsnDecodeSequenceItem items[] = {
838 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
839 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
840 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
841 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
842 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
843 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
844 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
845 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
846 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
847 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
848 Issuer.pbData) },
849 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
850 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
851 FALSE, 0 },
852 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
853 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
854 Subject.pbData) },
855 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
856 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
857 FALSE, TRUE, offsetof(CERT_INFO,
858 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
859 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
860 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
861 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
862 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
863 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
864 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
865 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
866 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
867 offsetof(CERT_INFO, rgExtension), 0 },
868 };
869
870 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
871 pDecodePara, pvStructInfo, *pcbStructInfo);
872
873 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
874 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
875 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
876
877 TRACE("Returning %d (%08x)\n", ret, GetLastError());
878 return ret;
879 }
880
881 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
882 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
883 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
884 {
885 BOOL ret = TRUE;
886
887 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
888 pDecodePara, pvStructInfo, *pcbStructInfo);
889
890 __TRY
891 {
892 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
893 DWORD size = 0;
894
895 /* First try to decode it as a signed cert. */
896 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
897 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
898 (BYTE *)&signedCert, &size);
899 if (ret)
900 {
901 size = 0;
902 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
903 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
904 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
905 pcbStructInfo);
906 LocalFree(signedCert);
907 }
908 /* Failing that, try it as an unsigned cert */
909 if (!ret)
910 {
911 size = 0;
912 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
913 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
914 pDecodePara, pvStructInfo, pcbStructInfo);
915 }
916 }
917 __EXCEPT_PAGE_FAULT
918 {
919 SetLastError(STATUS_ACCESS_VIOLATION);
920 ret = FALSE;
921 }
922 __ENDTRY
923
924 TRACE("Returning %d (%08x)\n", ret, GetLastError());
925 return ret;
926 }
927
928 static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
929 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
930 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
931 {
932 BOOL ret;
933 struct AsnDecodeSequenceItem items[] = {
934 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
935 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
936 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
937 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
938 sizeof(FILETIME), FALSE, FALSE, 0 },
939 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
940 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
941 offsetof(CRL_ENTRY, rgExtension), 0 },
942 };
943 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
944
945 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
946 *pcbStructInfo);
947
948 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
949 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
950 NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
951 return ret;
952 }
953
954 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
955 * been set prior to calling.
956 */
957 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
958 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
959 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
960 {
961 BOOL ret;
962 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
963 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
964 offsetof(CRL_ENTRY, SerialNumber.pbData) };
965 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
966
967 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
968 pDecodePara, pvStructInfo, *pcbStructInfo);
969
970 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
971 pDecodePara, pvStructInfo, pcbStructInfo,
972 entries ? entries->rgItems : NULL);
973 TRACE("Returning %d (%08x)\n", ret, GetLastError());
974 return ret;
975 }
976
977 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
978 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
979 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
980 {
981 struct AsnDecodeSequenceItem items[] = {
982 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
983 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
984 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
985 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
986 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
987 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
988 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
989 Issuer.pbData) },
990 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
991 sizeof(FILETIME), FALSE, FALSE, 0 },
992 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
993 sizeof(FILETIME), TRUE, FALSE, 0 },
994 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
995 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
996 offsetof(CRL_INFO, rgCRLEntry), 0 },
997 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
998 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
999 offsetof(CRL_INFO, rgExtension), 0 },
1000 };
1001 BOOL ret = TRUE;
1002
1003 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1004 pDecodePara, pvStructInfo, *pcbStructInfo);
1005
1006 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1007 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1008 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1009
1010 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1011 return ret;
1012 }
1013
1014 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1015 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1016 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1017 {
1018 BOOL ret = TRUE;
1019
1020 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1021 pDecodePara, pvStructInfo, *pcbStructInfo);
1022
1023 __TRY
1024 {
1025 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1026 DWORD size = 0;
1027
1028 /* First try to decode it as a signed crl. */
1029 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
1030 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1031 (BYTE *)&signedCrl, &size);
1032 if (ret)
1033 {
1034 size = 0;
1035 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1036 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1037 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1038 pvStructInfo, pcbStructInfo);
1039 LocalFree(signedCrl);
1040 }
1041 /* Failing that, try it as an unsigned crl */
1042 if (!ret)
1043 {
1044 size = 0;
1045 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1046 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1047 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1048 }
1049 }
1050 __EXCEPT_PAGE_FAULT
1051 {
1052 SetLastError(STATUS_ACCESS_VIOLATION);
1053 ret = FALSE;
1054 }
1055 __ENDTRY
1056
1057 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1058 return ret;
1059 }
1060
1061 static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
1062 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1063 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1064 {
1065 BOOL ret = TRUE;
1066
1067 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1068 pDecodePara, pvStructInfo, *pcbStructInfo);
1069
1070 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1071 {
1072 DWORD dataLen;
1073
1074 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1075 {
1076 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1077 DWORD bytesNeeded = sizeof(LPSTR);
1078
1079 if (dataLen)
1080 {
1081 /* The largest possible string for the first two components
1082 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1083 */
1084 char firstTwo[6];
1085 const BYTE *ptr;
1086
1087 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1088 pbEncoded[1 + lenBytes] / 40,
1089 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1090 * 40);
1091 bytesNeeded += strlen(firstTwo) + 1;
1092 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1093 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1094 {
1095 /* large enough for ".4000000" */
1096 char str[9];
1097 int val = 0;
1098
1099 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1100 (*ptr & 0x80))
1101 {
1102 val <<= 7;
1103 val |= *ptr & 0x7f;
1104 ptr++;
1105 }
1106 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1107 (*ptr & 0x80))
1108 {
1109 SetLastError(CRYPT_E_ASN1_CORRUPT);
1110 ret = FALSE;
1111 }
1112 else
1113 {
1114 val <<= 7;
1115 val |= *ptr++;
1116 snprintf(str, sizeof(str), ".%d", val);
1117 bytesNeeded += strlen(str);
1118 }
1119 }
1120 }
1121 if (!pvStructInfo)
1122 *pcbStructInfo = bytesNeeded;
1123 else if (*pcbStructInfo < bytesNeeded)
1124 {
1125 *pcbStructInfo = bytesNeeded;
1126 SetLastError(ERROR_MORE_DATA);
1127 ret = FALSE;
1128 }
1129 else
1130 {
1131 if (dataLen)
1132 {
1133 const BYTE *ptr;
1134 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1135
1136 *pszObjId = 0;
1137 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1138 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1139 40) * 40);
1140 pszObjId += strlen(pszObjId);
1141 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1142 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1143 {
1144 int val = 0;
1145
1146 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1147 (*ptr & 0x80))
1148 {
1149 val <<= 7;
1150 val |= *ptr & 0x7f;
1151 ptr++;
1152 }
1153 val <<= 7;
1154 val |= *ptr++;
1155 sprintf(pszObjId, ".%d", val);
1156 pszObjId += strlen(pszObjId);
1157 }
1158 }
1159 else
1160 *(LPSTR *)pvStructInfo = NULL;
1161 *pcbStructInfo = bytesNeeded;
1162 }
1163 }
1164 }
1165 return ret;
1166 }
1167
1168 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1169 * ahead of time!
1170 */
1171 static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
1172 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1173 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1174 {
1175 struct AsnDecodeSequenceItem items[] = {
1176 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1177 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1178 offsetof(CERT_EXTENSION, pszObjId), 0 },
1179 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1180 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1181 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1182 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1183 offsetof(CERT_EXTENSION, Value.pbData) },
1184 };
1185 BOOL ret = TRUE;
1186 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1187
1188 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1189 *pcbStructInfo);
1190
1191 if (ext)
1192 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1193 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1194 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1195 ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
1196 if (ext)
1197 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1198 debugstr_a(ext->pszObjId));
1199 TRACE("returning %d (%08x)\n", ret, GetLastError());
1200 return ret;
1201 }
1202
1203 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1204 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1205 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1206 {
1207 BOOL ret = TRUE;
1208 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1209 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1210 offsetof(CERT_EXTENSION, pszObjId) };
1211 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1212
1213 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1214 pDecodePara, pvStructInfo, *pcbStructInfo);
1215
1216 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1217 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1218 return ret;
1219 }
1220
1221 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1222 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1223 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1224 {
1225 BOOL ret = TRUE;
1226
1227 __TRY
1228 {
1229 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1230 lpszStructType, pbEncoded, cbEncoded,
1231 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1232 if (ret && pvStructInfo)
1233 {
1234 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1235 pcbStructInfo, *pcbStructInfo);
1236 if (ret)
1237 {
1238 CERT_EXTENSIONS *exts;
1239
1240 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1241 pvStructInfo = *(BYTE **)pvStructInfo;
1242 exts = (CERT_EXTENSIONS *)pvStructInfo;
1243 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1244 sizeof(CERT_EXTENSIONS));
1245 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1246 lpszStructType, pbEncoded, cbEncoded,
1247 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1248 pcbStructInfo);
1249 }
1250 }
1251 }
1252 __EXCEPT_PAGE_FAULT
1253 {
1254 SetLastError(STATUS_ACCESS_VIOLATION);
1255 ret = FALSE;
1256 }
1257 __ENDTRY
1258 return ret;
1259 }
1260
1261 /* Warning: this assumes the address of value->Value.pbData is already set, in
1262 * order to avoid overwriting memory. (In some cases, it may change it, if it
1263 * doesn't copy anything to memory.) Be sure to set it correctly!
1264 */
1265 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1266 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1267 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1268 {
1269 BOOL ret = TRUE;
1270 DWORD dataLen;
1271 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1272
1273 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1274 {
1275 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1276 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1277
1278 switch (pbEncoded[0])
1279 {
1280 case ASN_OCTETSTRING:
1281 valueType = CERT_RDN_OCTET_STRING;
1282 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1283 bytesNeeded += dataLen;
1284 break;
1285 case ASN_NUMERICSTRING:
1286 valueType = CERT_RDN_NUMERIC_STRING;
1287 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1288 bytesNeeded += dataLen;
1289 break;
1290 case ASN_PRINTABLESTRING:
1291 valueType = CERT_RDN_PRINTABLE_STRING;
1292 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1293 bytesNeeded += dataLen;
1294 break;
1295 case ASN_IA5STRING:
1296 valueType = CERT_RDN_IA5_STRING;
1297 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1298 bytesNeeded += dataLen;
1299 break;
1300 case ASN_T61STRING:
1301 valueType = CERT_RDN_T61_STRING;
1302 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1303 bytesNeeded += dataLen;
1304 break;
1305 case ASN_VIDEOTEXSTRING:
1306 valueType = CERT_RDN_VIDEOTEX_STRING;
1307 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1308 bytesNeeded += dataLen;
1309 break;
1310 case ASN_GRAPHICSTRING:
1311 valueType = CERT_RDN_GRAPHIC_STRING;
1312 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1313 bytesNeeded += dataLen;
1314 break;
1315 case ASN_VISIBLESTRING:
1316 valueType = CERT_RDN_VISIBLE_STRING;
1317 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1318 bytesNeeded += dataLen;
1319 break;
1320 case ASN_GENERALSTRING:
1321 valueType = CERT_RDN_GENERAL_STRING;
1322 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1323 bytesNeeded += dataLen;
1324 break;
1325 case ASN_UNIVERSALSTRING:
1326 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1327 SetLastError(CRYPT_E_ASN1_BADTAG);
1328 return FALSE;
1329 case ASN_BMPSTRING:
1330 valueType = CERT_RDN_BMP_STRING;
1331 bytesNeeded += dataLen;
1332 break;
1333 case ASN_UTF8STRING:
1334 valueType = CERT_RDN_UTF8_STRING;
1335 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1336 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1337 break;
1338 default:
1339 SetLastError(CRYPT_E_ASN1_BADTAG);
1340 return FALSE;
1341 }
1342
1343 if (!value)
1344 *pcbStructInfo = bytesNeeded;
1345 else if (*pcbStructInfo < bytesNeeded)
1346 {
1347 *pcbStructInfo = bytesNeeded;
1348 SetLastError(ERROR_MORE_DATA);
1349 ret = FALSE;
1350 }
1351 else
1352 {
1353 *pcbStructInfo = bytesNeeded;
1354 value->dwValueType = valueType;
1355 if (dataLen)
1356 {
1357 DWORD i;
1358
1359 assert(value->Value.pbData);
1360 switch (pbEncoded[0])
1361 {
1362 case ASN_OCTETSTRING:
1363 case ASN_NUMERICSTRING:
1364 case ASN_PRINTABLESTRING:
1365 case ASN_IA5STRING:
1366 case ASN_T61STRING:
1367 case ASN_VIDEOTEXSTRING:
1368 case ASN_GRAPHICSTRING:
1369 case ASN_VISIBLESTRING:
1370 case ASN_GENERALSTRING:
1371 value->Value.cbData = dataLen;
1372 if (dataLen)
1373 {
1374 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1375 memcpy(value->Value.pbData,
1376 pbEncoded + 1 + lenBytes, dataLen);
1377 else
1378 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1379 lenBytes;
1380 }
1381 break;
1382 case ASN_BMPSTRING:
1383 {
1384 LPWSTR str = (LPWSTR)value->Value.pbData;
1385
1386 value->Value.cbData = dataLen;
1387 for (i = 0; i < dataLen / 2; i++)
1388 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1389 pbEncoded[1 + lenBytes + 2 * i + 1];
1390 break;
1391 }
1392 case ASN_UTF8STRING:
1393 {
1394 LPWSTR str = (LPWSTR)value->Value.pbData;
1395
1396 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1397 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1398 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1399 break;
1400 }
1401 }
1402 }
1403 else
1404 {
1405 value->Value.cbData = 0;
1406 value->Value.pbData = NULL;
1407 }
1408 }
1409 }
1410 return ret;
1411 }
1412
1413 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1414 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1415 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1416 {
1417 BOOL ret = TRUE;
1418
1419 __TRY
1420 {
1421 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1422 lpszStructType, pbEncoded, cbEncoded,
1423 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1424 if (ret && pvStructInfo)
1425 {
1426 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1427 pcbStructInfo, *pcbStructInfo);
1428 if (ret)
1429 {
1430 CERT_NAME_VALUE *value;
1431
1432 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1433 pvStructInfo = *(BYTE **)pvStructInfo;
1434 value = (CERT_NAME_VALUE *)pvStructInfo;
1435 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1436 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1437 lpszStructType, pbEncoded, cbEncoded,
1438 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1439 pcbStructInfo);
1440 }
1441 }
1442 }
1443 __EXCEPT_PAGE_FAULT
1444 {
1445 SetLastError(STATUS_ACCESS_VIOLATION);
1446 ret = FALSE;
1447 }
1448 __ENDTRY
1449 return ret;
1450 }
1451
1452 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1453 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1454 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1455 void *pvStructInfo, DWORD *pcbStructInfo)
1456 {
1457 BOOL ret = TRUE;
1458 DWORD dataLen;
1459 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1460
1461 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1462 {
1463 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1464 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1465
1466 switch (pbEncoded[0])
1467 {
1468 case ASN_NUMERICSTRING:
1469 valueType = CERT_RDN_NUMERIC_STRING;
1470 bytesNeeded += dataLen * 2;
1471 break;
1472 case ASN_PRINTABLESTRING:
1473 valueType = CERT_RDN_PRINTABLE_STRING;
1474 bytesNeeded += dataLen * 2;
1475 break;
1476 case ASN_IA5STRING:
1477 valueType = CERT_RDN_IA5_STRING;
1478 bytesNeeded += dataLen * 2;
1479 break;
1480 case ASN_T61STRING:
1481 valueType = CERT_RDN_T61_STRING;
1482 bytesNeeded += dataLen * 2;
1483 break;
1484 case ASN_VIDEOTEXSTRING:
1485 valueType = CERT_RDN_VIDEOTEX_STRING;
1486 bytesNeeded += dataLen * 2;
1487 break;
1488 case ASN_GRAPHICSTRING:
1489 valueType = CERT_RDN_GRAPHIC_STRING;
1490 bytesNeeded += dataLen * 2;
1491 break;
1492 case ASN_VISIBLESTRING:
1493 valueType = CERT_RDN_VISIBLE_STRING;
1494 bytesNeeded += dataLen * 2;
1495 break;
1496 case ASN_GENERALSTRING:
1497 valueType = CERT_RDN_GENERAL_STRING;
1498 bytesNeeded += dataLen * 2;
1499 break;
1500 case ASN_UNIVERSALSTRING:
1501 valueType = CERT_RDN_UNIVERSAL_STRING;
1502 bytesNeeded += dataLen / 2;
1503 break;
1504 case ASN_BMPSTRING:
1505 valueType = CERT_RDN_BMP_STRING;
1506 bytesNeeded += dataLen;
1507 break;
1508 case ASN_UTF8STRING:
1509 valueType = CERT_RDN_UTF8_STRING;
1510 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1511 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1512 break;
1513 default:
1514 SetLastError(CRYPT_E_ASN1_BADTAG);
1515 return FALSE;
1516 }
1517
1518 if (!value)
1519 *pcbStructInfo = bytesNeeded;
1520 else if (*pcbStructInfo < bytesNeeded)
1521 {
1522 *pcbStructInfo = bytesNeeded;
1523 SetLastError(ERROR_MORE_DATA);
1524 ret = FALSE;
1525 }
1526 else
1527 {
1528 *pcbStructInfo = bytesNeeded;
1529 value->dwValueType = valueType;
1530 if (dataLen)
1531 {
1532 DWORD i;
1533 LPWSTR str = (LPWSTR)value->Value.pbData;
1534
1535 assert(value->Value.pbData);
1536 switch (pbEncoded[0])
1537 {
1538 case ASN_NUMERICSTRING:
1539 case ASN_PRINTABLESTRING:
1540 case ASN_IA5STRING:
1541 case ASN_T61STRING:
1542 case ASN_VIDEOTEXSTRING:
1543 case ASN_GRAPHICSTRING:
1544 case ASN_VISIBLESTRING:
1545 case ASN_GENERALSTRING:
1546 value->Value.cbData = dataLen * 2;
1547 for (i = 0; i < dataLen; i++)
1548 str[i] = pbEncoded[1 + lenBytes + i];
1549 break;
1550 case ASN_UNIVERSALSTRING:
1551 value->Value.cbData = dataLen / 2;
1552 for (i = 0; i < dataLen / 4; i++)
1553 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1554 | pbEncoded[1 + lenBytes + 2 * i + 3];
1555 break;
1556 case ASN_BMPSTRING:
1557 value->Value.cbData = dataLen;
1558 for (i = 0; i < dataLen / 2; i++)
1559 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1560 pbEncoded[1 + lenBytes + 2 * i + 1];
1561 break;
1562 case ASN_UTF8STRING:
1563 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1564 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1565 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1566 break;
1567 }
1568 }
1569 else
1570 {
1571 value->Value.cbData = 0;
1572 value->Value.pbData = NULL;
1573 }
1574 }
1575 }
1576 return ret;
1577 }
1578
1579 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1580 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1581 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1582 {
1583 BOOL ret = TRUE;
1584
1585 __TRY
1586 {
1587 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1588 lpszStructType, pbEncoded, cbEncoded,
1589 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1590 if (ret && pvStructInfo)
1591 {
1592 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1593 pcbStructInfo, *pcbStructInfo);
1594 if (ret)
1595 {
1596 CERT_NAME_VALUE *value;
1597
1598 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1599 pvStructInfo = *(BYTE **)pvStructInfo;
1600 value = (CERT_NAME_VALUE *)pvStructInfo;
1601 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1602 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1603 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1604 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1605 pcbStructInfo);
1606 }
1607 }
1608 }
1609 __EXCEPT_PAGE_FAULT
1610 {
1611 SetLastError(STATUS_ACCESS_VIOLATION);
1612 ret = FALSE;
1613 }
1614 __ENDTRY
1615 return ret;
1616 }
1617
1618 static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
1619 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1620 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1621 {
1622 BOOL ret;
1623 struct AsnDecodeSequenceItem items[] = {
1624 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1625 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1626 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1627 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1628 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1629 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1630 };
1631 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1632
1633 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1634 pvStructInfo, *pcbStructInfo);
1635
1636 if (attr)
1637 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1638 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1639 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1640 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1641 if (attr)
1642 {
1643 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1644 debugstr_a(attr->pszObjId));
1645 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1646 }
1647 TRACE("returning %d (%08x)\n", ret, GetLastError());
1648 return ret;
1649 }
1650
1651 static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
1652 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1653 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1654 {
1655 BOOL ret = TRUE;
1656 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1657 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1658 offsetof(CERT_RDN_ATTR, pszObjId) };
1659 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1660
1661 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1662 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1663 return ret;
1664 }
1665
1666 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1667 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1668 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1669 {
1670 BOOL ret = TRUE;
1671
1672 __TRY
1673 {
1674 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1675 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1676 offsetof(CERT_RDN, rgRDNAttr) };
1677
1678 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1679 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1680 }
1681 __EXCEPT_PAGE_FAULT
1682 {
1683 SetLastError(STATUS_ACCESS_VIOLATION);
1684 ret = FALSE;
1685 }
1686 __ENDTRY
1687 return ret;
1688 }
1689
1690 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
1691 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1692 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1693 {
1694 BOOL ret;
1695 struct AsnDecodeSequenceItem items[] = {
1696 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1697 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1698 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1699 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1700 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1701 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1702 };
1703 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1704
1705 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1706 pvStructInfo, *pcbStructInfo);
1707
1708 if (attr)
1709 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1710 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1711 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1712 attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
1713 if (attr)
1714 {
1715 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1716 debugstr_a(attr->pszObjId));
1717 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1718 }
1719 TRACE("returning %d (%08x)\n", ret, GetLastError());
1720 return ret;
1721 }
1722
1723 static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
1724 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1725 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1726 {
1727 BOOL ret = TRUE;
1728 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1729 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1730 offsetof(CERT_RDN_ATTR, pszObjId) };
1731 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1732
1733 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1734 pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1735 return ret;
1736 }
1737
1738 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1739 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1740 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1741 {
1742 BOOL ret = TRUE;
1743
1744 __TRY
1745 {
1746 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1747 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1748 offsetof(CERT_RDN, rgRDNAttr) };
1749
1750 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1751 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1752 }
1753 __EXCEPT_PAGE_FAULT
1754 {
1755 SetLastError(STATUS_ACCESS_VIOLATION);
1756 ret = FALSE;
1757 }
1758 __ENDTRY
1759 return ret;
1760 }
1761
1762 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1763 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1764 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1765 {
1766 BOOL ret = TRUE;
1767 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1768
1769 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1770 pDecodePara, pvStructInfo, *pcbStructInfo);
1771
1772 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1773 bytesNeeded += cbEncoded;
1774 if (!pvStructInfo)
1775 *pcbStructInfo = bytesNeeded;
1776 else if (*pcbStructInfo < bytesNeeded)
1777 {
1778 SetLastError(ERROR_MORE_DATA);
1779 *pcbStructInfo = bytesNeeded;
1780 ret = FALSE;
1781 }
1782 else
1783 {
1784 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1785
1786 *pcbStructInfo = bytesNeeded;
1787 blob->cbData = cbEncoded;
1788 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1789 blob->pbData = (LPBYTE)pbEncoded;
1790 else
1791 {
1792 assert(blob->pbData);
1793 memcpy(blob->pbData, pbEncoded, blob->cbData);
1794 }
1795 }
1796 return ret;
1797 }
1798
1799 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1800 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1801 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1802 {
1803 CRYPT_ALGORITHM_IDENTIFIER *algo =
1804 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1805 BOOL ret = TRUE;
1806 struct AsnDecodeSequenceItem items[] = {
1807 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1808 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
1809 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1810 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1811 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1812 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1813 };
1814
1815 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1816 pDecodePara, pvStructInfo, *pcbStructInfo);
1817
1818 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1819 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1820 pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1821 if (ret && pvStructInfo)
1822 {
1823 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1824 debugstr_a(algo->pszObjId));
1825 }
1826 return ret;
1827 }
1828
1829 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
1830 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1831 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1832 {
1833 BOOL ret = TRUE;
1834 struct AsnDecodeSequenceItem items[] = {
1835 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
1836 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1837 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
1838 Algorithm.pszObjId) },
1839 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
1840 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1841 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
1842 };
1843 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1844
1845 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1846 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1847 pDecodePara, pvStructInfo, pcbStructInfo, info ?
1848 info->Algorithm.Parameters.pbData : NULL);
1849 return ret;
1850 }
1851
1852 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
1853 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1854 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1855 {
1856 BOOL ret = TRUE;
1857
1858 __TRY
1859 {
1860 DWORD bytesNeeded;
1861
1862 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1863 lpszStructType, pbEncoded, cbEncoded,
1864 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1865 {
1866 if (!pvStructInfo)
1867 *pcbStructInfo = bytesNeeded;
1868 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1869 pvStructInfo, pcbStructInfo, bytesNeeded)))
1870 {
1871 PCERT_PUBLIC_KEY_INFO info;
1872
1873 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1874 pvStructInfo = *(BYTE **)pvStructInfo;
1875 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
1876 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
1877 sizeof(CERT_PUBLIC_KEY_INFO);
1878 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
1879 lpszStructType, pbEncoded, cbEncoded,
1880 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1881 &bytesNeeded);
1882 }
1883 }
1884 }
1885 __EXCEPT_PAGE_FAULT
1886 {
1887 SetLastError(STATUS_ACCESS_VIOLATION);
1888 ret = FALSE;
1889 }
1890 __ENDTRY
1891 return ret;
1892 }
1893
1894 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
1895 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1896 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1897 {
1898 BOOL ret;
1899
1900 if (cbEncoded < 3)
1901 {
1902 SetLastError(CRYPT_E_ASN1_CORRUPT);
1903 return FALSE;
1904 }
1905 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
1906 {
1907 SetLastError(CRYPT_E_ASN1_CORRUPT);
1908 return FALSE;
1909 }
1910 if (pbEncoded[1] > 1)
1911 {
1912 SetLastError(CRYPT_E_ASN1_CORRUPT);
1913 return FALSE;
1914 }
1915 if (!pvStructInfo)
1916 {
1917 *pcbStructInfo = sizeof(BOOL);
1918 ret = TRUE;
1919 }
1920 else if (*pcbStructInfo < sizeof(BOOL))
1921 {
1922 *pcbStructInfo = sizeof(BOOL);
1923 SetLastError(ERROR_MORE_DATA);
1924 ret = FALSE;
1925 }
1926 else
1927 {
1928 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
1929 ret = TRUE;
1930 }
1931 TRACE("returning %d (%08x)\n", ret, GetLastError());
1932 return ret;
1933 }
1934
1935 static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
1936 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1937 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1938 {
1939 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
1940 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
1941 BOOL ret;
1942
1943 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1944 pDecodePara, pvStructInfo, *pcbStructInfo);
1945
1946 if (cbEncoded < 2)
1947 {
1948 SetLastError(CRYPT_E_ASN1_CORRUPT);
1949 return FALSE;
1950 }
1951 if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
1952 {
1953 SetLastError(CRYPT_E_ASN1_BADTAG);
1954 return FALSE;
1955 }
1956 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1957 if (1 + lenBytes > cbEncoded)
1958 {
1959 SetLastError(CRYPT_E_ASN1_CORRUPT);
1960 return FALSE;
1961 }
1962 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1963 {
1964 switch (pbEncoded[0] & ASN_TYPE_MASK)
1965 {
1966 case 1: /* rfc822Name */
1967 case 2: /* dNSName */
1968 case 6: /* uniformResourceIdentifier */
1969 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1970 break;
1971 case 7: /* iPAddress */
1972 bytesNeeded += dataLen;
1973 break;
1974 case 8: /* registeredID */
1975 /* FIXME: decode as OID */
1976 case 0: /* otherName */
1977 case 4: /* directoryName */
1978 FIXME("stub\n");
1979 SetLastError(CRYPT_E_ASN1_BADTAG);
1980 ret = FALSE;
1981 break;
1982 case 3: /* x400Address, unimplemented */
1983 case 5: /* ediPartyName, unimplemented */
1984 SetLastError(CRYPT_E_ASN1_BADTAG);
1985 ret = FALSE;
1986 break;
1987 default:
1988 SetLastError(CRYPT_E_ASN1_CORRUPT);
1989 ret = FALSE;
1990 }
1991 if (ret)
1992 {
1993 if (!entry)
1994 *pcbStructInfo = bytesNeeded;
1995 else if (*pcbStructInfo < bytesNeeded)
1996 {
1997 *pcbStructInfo = bytesNeeded;
1998 SetLastError(ERROR_MORE_DATA);
1999 ret = FALSE;
2000 }
2001 else
2002 {
2003 *pcbStructInfo = bytesNeeded;
2004 /* MS used values one greater than the asn1 ones.. sigh */
2005 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2006 switch (pbEncoded[0] & ASN_TYPE_MASK)
2007 {
2008 case 1: /* rfc822Name */
2009 case 2: /* dNSName */
2010 case 6: /* uniformResourceIdentifier */
2011 {
2012 DWORD i;
2013
2014 for (i = 0; i < dataLen; i++)
2015 entry->u.pwszURL[i] =
2016 (WCHAR)pbEncoded[1 + lenBytes + i];
2017 entry->u.pwszURL[i] = 0;
2018 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2019 debugstr_w(entry->u.pwszURL));
2020 break;
2021 }
2022 case 7: /* iPAddress */
2023 /* The next data pointer is in the pwszURL spot, that is,
2024 * the first 4 bytes. Need to move it to the next spot.
2025 */
2026 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2027 entry->u.IPAddress.cbData = dataLen;
2028 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2029 dataLen);
2030 break;
2031 }
2032 }
2033 }
2034 }
2035 return ret;
2036 }
2037
2038 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2039 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2040 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2041 {
2042 BOOL ret = TRUE;
2043 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2044 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2045 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2046 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2047
2048 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2049 pDecodePara, pvStructInfo, *pcbStructInfo);
2050
2051 if (info)
2052 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2053 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2054 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2055 return ret;
2056 }
2057
2058 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2059 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2060 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2061 {
2062 BOOL ret;
2063
2064 __TRY
2065 {
2066 struct AsnDecodeSequenceItem items[] = {
2067 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2068 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
2069 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2070 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2071 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2072 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2073 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2074 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2075 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2076 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2077 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2078 };
2079
2080 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2081 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2082 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2083 }
2084 __EXCEPT_PAGE_FAULT
2085 {
2086 SetLastError(STATUS_ACCESS_VIOLATION);
2087 ret = FALSE;
2088 }
2089 __ENDTRY
2090 return ret;
2091 }
2092
2093 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2094 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2095 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2096 {
2097 BOOL ret = TRUE;
2098
2099 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2100 pDecodePara, pvStructInfo, *pcbStructInfo);
2101
2102 __TRY
2103 {
2104 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2105 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2106 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2107
2108 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2109 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2110 }
2111 __EXCEPT_PAGE_FAULT
2112 {
2113 SetLastError(STATUS_ACCESS_VIOLATION);
2114 ret = FALSE;
2115 }
2116 __ENDTRY
2117 return ret;
2118 }
2119
2120 struct PATH_LEN_CONSTRAINT
2121 {
2122 BOOL fPathLenConstraint;
2123 DWORD dwPathLenConstraint;
2124 };
2125
2126 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2127 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2128 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2129 {
2130 BOOL ret = TRUE;
2131
2132 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2133 pvStructInfo, *pcbStructInfo);
2134
2135 if (cbEncoded)
2136 {
2137 if (pbEncoded[0] == ASN_INTEGER)
2138 {
2139 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2140
2141 if (!pvStructInfo)
2142 *pcbStructInfo = bytesNeeded;
2143 else if (*pcbStructInfo < bytesNeeded)
2144 {
2145 SetLastError(ERROR_MORE_DATA);
2146 *pcbStructInfo = bytesNeeded;
2147 ret = FALSE;
2148 }
2149 else
2150 {
2151 struct PATH_LEN_CONSTRAINT *constraint =
2152 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2153 DWORD size = sizeof(constraint->dwPathLenConstraint);
2154
2155 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2156 pbEncoded, cbEncoded, 0, NULL,
2157 &constraint->dwPathLenConstraint, &size);
2158 if (ret)
2159 constraint->fPathLenConstraint = TRUE;
2160 TRACE("got an int, dwPathLenConstraint is %d\n",
2161 constraint->dwPathLenConstraint);
2162 }
2163 }
2164 else
2165 {
2166 SetLastError(CRYPT_E_ASN1_CORRUPT);
2167 ret = FALSE;
2168 }
2169 }
2170 TRACE("returning %d (%08x)\n", ret, GetLastError());
2171 return ret;
2172 }
2173
2174 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2175 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2176 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2177 {
2178 BOOL ret;
2179 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2180 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2181 offsetof(CERT_NAME_BLOB, pbData) };
2182 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2183
2184 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2185 pDecodePara, pvStructInfo, *pcbStructInfo);
2186
2187 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2188 pDecodePara, pvStructInfo, pcbStructInfo,
2189 entries ? entries->rgItems : NULL);
2190 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2191 return ret;
2192 }
2193
2194 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2195 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2196 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2197 {
2198 BOOL ret;
2199
2200 __TRY
2201 {
2202 struct AsnDecodeSequenceItem items[] = {
2203 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2204 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2205 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2206 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2207 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2208 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2209 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2210 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2211 sizeof(struct GenericArray), TRUE, TRUE,
2212 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2213 };
2214
2215 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2216 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2217 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2218 }
2219 __EXCEPT_PAGE_FAULT
2220 {
2221 SetLastError(STATUS_ACCESS_VIOLATION);
2222 ret = FALSE;
2223 }
2224 __ENDTRY
2225 return ret;
2226 }
2227
2228 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2229 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2230 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2231 {
2232 BOOL ret;
2233
2234 __TRY
2235 {
2236 struct AsnDecodeSequenceItem items[] = {
2237 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2238 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2239 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2240 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2241 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2242 };
2243
2244 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2245 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2246 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2247 }
2248 __EXCEPT_PAGE_FAULT
2249 {
2250 SetLastError(STATUS_ACCESS_VIOLATION);
2251 ret = FALSE;
2252 }
2253 __ENDTRY
2254 return ret;
2255 }
2256
2257 #define RSA1_MAGIC 0x31415352
2258
2259 struct DECODED_RSA_PUB_KEY
2260 {
2261 DWORD pubexp;
2262 CRYPT_INTEGER_BLOB modulus;
2263 };
2264
2265 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2266 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2267 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2268 {
2269 BOOL ret;
2270
2271 __TRY
2272 {
2273 struct AsnDecodeSequenceItem items[] = {
2274 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2275 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2276 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2277 0 },
2278 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2279 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2280 };
2281 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2282 DWORD size = 0;
2283
2284 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2285 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2286 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
2287 if (ret)
2288 {
2289 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2290 decodedKey->modulus.cbData;
2291
2292 if (!pvStructInfo)
2293 {
2294 *pcbStructInfo = bytesNeeded;
2295 ret = TRUE;
2296 }
2297 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2298 pvStructInfo, pcbStructInfo, bytesNeeded)))
2299 {
2300 BLOBHEADER *hdr;
2301 RSAPUBKEY *rsaPubKey;
2302
2303 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2304 pvStructInfo = *(BYTE **)pvStructInfo;
2305 hdr = (BLOBHEADER *)pvStructInfo;
2306 hdr->bType = PUBLICKEYBLOB;
2307 hdr->bVersion = CUR_BLOB_VERSION;
2308 hdr->reserved = 0;
2309 hdr->aiKeyAlg = CALG_RSA_KEYX;
2310 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2311 sizeof(BLOBHEADER));
2312 rsaPubKey->magic = RSA1_MAGIC;
2313 rsaPubKey->pubexp = decodedKey->pubexp;
2314 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2315 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2316 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2317 decodedKey->modulus.cbData);
2318 }
2319 LocalFree(decodedKey);
2320 }
2321 }
2322 __EXCEPT_PAGE_FAULT
2323 {
2324 SetLastError(STATUS_ACCESS_VIOLATION);
2325 ret = FALSE;
2326 }
2327 __ENDTRY
2328 return ret;
2329 }
2330
2331 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2332 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2333 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2334 {
2335 BOOL ret;
2336 DWORD bytesNeeded, dataLen;
2337
2338 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2339 pDecodePara, pvStructInfo, *pcbStructInfo);
2340
2341 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2342 {
2343 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2344 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2345 else
2346 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2347 if (!pvStructInfo)
2348 *pcbStructInfo = bytesNeeded;
2349 else if (*pcbStructInfo < bytesNeeded)
2350 {
2351 SetLastError(ERROR_MORE_DATA);
2352 *pcbStructInfo = bytesNeeded;
2353 ret = FALSE;
2354 }
2355 else
2356 {
2357 CRYPT_DATA_BLOB *blob;
2358 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2359
2360 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2361 blob->cbData = dataLen;
2362 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2363 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2364 else
2365 {
2366 assert(blob->pbData);
2367 if (blob->cbData)
2368 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2369 blob->cbData);
2370 }
2371 }
2372 }
2373 return ret;
2374 }
2375
2376 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2377 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2378 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2379 {
2380 BOOL ret;
2381
2382 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2383 pDecodePara, pvStructInfo, *pcbStructInfo);
2384
2385 __TRY
2386 {
2387 DWORD bytesNeeded;
2388
2389 if (!cbEncoded)
2390 {
2391 SetLastError(CRYPT_E_ASN1_CORRUPT);
2392 ret = FALSE;
2393 }
2394 else if (pbEncoded[0] != ASN_OCTETSTRING)
2395 {
2396 SetLastError(CRYPT_E_ASN1_BADTAG);
2397 ret = FALSE;
2398 }
2399 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2400 lpszStructType, pbEncoded, cbEncoded,
2401 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2402 {
2403 if (!pvStructInfo)
2404 *pcbStructInfo = bytesNeeded;
2405 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2406 pvStructInfo, pcbStructInfo, bytesNeeded)))
2407 {
2408 CRYPT_DATA_BLOB *blob;
2409
2410 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2411 pvStructInfo = *(BYTE **)pvStructInfo;
2412 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2413 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2414 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2415 lpszStructType, pbEncoded, cbEncoded,
2416 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2417 &bytesNeeded);
2418 }
2419 }
2420 }
2421 __EXCEPT_PAGE_FAULT
2422 {
2423 SetLastError(STATUS_ACCESS_VIOLATION);
2424 ret = FALSE;
2425 }
2426 __ENDTRY
2427 return ret;
2428 }
2429
2430 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2431 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2432 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2433 {
2434 BOOL ret;
2435
2436 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2437 pDecodePara, pvStructInfo, *pcbStructInfo);
2438
2439 if (pbEncoded[0] == ASN_BITSTRING)
2440 {
2441 DWORD bytesNeeded, dataLen;
2442
2443 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2444 {
2445 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2446 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2447 else
2448 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2449 if (!pvStructInfo)
2450 *pcbStructInfo = bytesNeeded;
2451 else if (*pcbStructInfo < bytesNeeded)
2452 {
2453 *pcbStructInfo = bytesNeeded;
2454 SetLastError(ERROR_MORE_DATA);
2455 ret = FALSE;
2456 }
2457 else
2458 {
2459 CRYPT_BIT_BLOB *blob;
2460
2461 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2462 blob->cbData = dataLen - 1;
2463 blob->cUnusedBits = *(pbEncoded + 1 +
2464 GET_LEN_BYTES(pbEncoded[1]));
2465 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2466 {
2467 blob->pbData = (BYTE *)pbEncoded + 2 +
2468 GET_LEN_BYTES(pbEncoded[1]);
2469 }
2470 else
2471 {
2472 assert(blob->pbData);
2473 if (blob->cbData)
2474 {
2475 BYTE mask = 0xff << blob->cUnusedBits;
2476
2477 memcpy(blob->pbData, pbEncoded + 2 +
2478 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2479 blob->pbData[blob->cbData - 1] &= mask;
2480 }
2481 }
2482 }
2483 }
2484 }
2485 else
2486 {
2487 SetLastError(CRYPT_E_ASN1_BADTAG);
2488 ret = FALSE;
2489 }
2490 TRACE("returning %d (%08x)\n", ret, GetLastError());
2491 return ret;
2492 }
2493
2494 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2495 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2496 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2497 {
2498 BOOL ret;
2499
2500 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2501 pDecodePara, pvStructInfo, pcbStructInfo);
2502
2503 __TRY
2504 {
2505 DWORD bytesNeeded;
2506
2507 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2508 lpszStructType, pbEncoded, cbEncoded,
2509 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2510 {
2511 if (!pvStructInfo)
2512 *pcbStructInfo = bytesNeeded;
2513 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2514 pvStructInfo, pcbStructInfo, bytesNeeded)))
2515 {
2516 CRYPT_BIT_BLOB *blob;
2517
2518 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2519 pvStructInfo = *(BYTE **)pvStructInfo;
2520 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2521 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2522 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2523 lpszStructType, pbEncoded, cbEncoded,
2524 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2525 &bytesNeeded);
2526 }
2527 }
2528 }
2529 __EXCEPT_PAGE_FAULT
2530 {
2531 SetLastError(STATUS_ACCESS_VIOLATION);
2532 ret = FALSE;
2533 }
2534 __ENDTRY
2535 TRACE("returning %d (%08x)\n", ret, GetLastError());
2536 return ret;
2537 }
2538
2539 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2540 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2541 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2542 {
2543 BOOL ret;
2544
2545 if (!pvStructInfo)
2546 {
2547 *pcbStructInfo = sizeof(int);
2548 return TRUE;
2549 }
2550 __TRY
2551 {
2552 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2553 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2554 DWORD size = sizeof(buf);
2555
2556 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2557 if (pbEncoded[0] != ASN_INTEGER)
2558 {
2559 SetLastError(CRYPT_E_ASN1_BADTAG);
2560 ret = FALSE;
2561 }
2562 else
2563 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2564 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
2565 &size);
2566 if (ret)
2567 {
2568 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2569 pvStructInfo, pcbStructInfo, sizeof(int))))
2570 {
2571 int val, i;
2572
2573 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2574 pvStructInfo = *(BYTE **)pvStructInfo;
2575 if (blob->pbData[blob->cbData - 1] & 0x80)
2576 {
2577 /* initialize to a negative value to sign-extend */
2578 val = -1;
2579 }
2580 else
2581 val = 0;
2582 for (i = 0; i < blob->cbData; i++)
2583 {
2584 val <<= 8;
2585 val |= blob->pbData[blob->cbData - i - 1];
2586 }
2587 memcpy(pvStructInfo, &val, sizeof(int));
2588 }
2589 }
2590 else if (GetLastError() == ERROR_MORE_DATA)
2591 SetLastError(CRYPT_E_ASN1_LARGE);
2592 }
2593 __EXCEPT_PAGE_FAULT
2594 {
2595 SetLastError(STATUS_ACCESS_VIOLATION);
2596 ret = FALSE;
2597 }
2598 __ENDTRY
2599 return ret;
2600 }
2601
2602 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
2603 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2604 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2605 {
2606 BOOL ret;
2607 DWORD bytesNeeded, dataLen;
2608
2609 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2610 {
2611 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2612
2613 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2614 if (!pvStructInfo)
2615 *pcbStructInfo = bytesNeeded;
2616 else if (*pcbStructInfo < bytesNeeded)
2617 {
2618 *pcbStructInfo = bytesNeeded;
2619 SetLastError(ERROR_MORE_DATA);
2620 ret = FALSE;
2621 }
2622 else
2623 {
2624 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2625
2626 blob->cbData = dataLen;
2627 assert(blob->pbData);
2628 if (blob->cbData)
2629 {
2630 DWORD i;
2631
2632 for (i = 0; i < blob->cbData; i++)
2633 {
2634 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2635 dataLen - i - 1);
2636 }
2637 }
2638 }
2639 }
2640 return ret;
2641 }
2642
2643 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
2644 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2645 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2646 {
2647 BOOL ret;
2648
2649 __TRY
2650 {
2651 DWORD bytesNeeded;
2652
2653 if (pbEncoded[0] != ASN_INTEGER)
2654 {
2655 SetLastError(CRYPT_E_ASN1_BADTAG);
2656 ret = FALSE;
2657 }
2658 else
2659 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2660 lpszStructType, pbEncoded, cbEncoded,
2661 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
2662 if (ret)
2663 {
2664 if (!pvStructInfo)
2665 *pcbStructInfo = bytesNeeded;
2666 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2667 pvStructInfo, pcbStructInfo, bytesNeeded)))
2668 {
2669 CRYPT_INTEGER_BLOB *blob;
2670
2671 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2672 pvStructInfo = *(BYTE **)pvStructInfo;
2673 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2674 blob->pbData = (BYTE *)pvStructInfo +
2675 sizeof(CRYPT_INTEGER_BLOB);
2676 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
2677 lpszStructType, pbEncoded, cbEncoded,
2678 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2679 &bytesNeeded);
2680 }
2681 }
2682 }
2683 __EXCEPT_PAGE_FAULT
2684 {
2685 SetLastError(STATUS_ACCESS_VIOLATION);
2686 ret = FALSE;
2687 }
2688 __ENDTRY
2689 return ret;
2690 }
2691
2692 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
2693 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2694 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2695 void *pvStructInfo, DWORD *pcbStructInfo)
2696 {
2697 BOOL ret;
2698
2699 if (pbEncoded[0] == ASN_INTEGER)
2700 {
2701 DWORD bytesNeeded, dataLen;
2702
2703 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2704 {
2705 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2706
2707 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2708 if (!pvStructInfo)
2709 *pcbStructInfo = bytesNeeded;
2710 else if (*pcbStructInfo < bytesNeeded)
2711 {
2712 *pcbStructInfo = bytesNeeded;
2713 SetLastError(ERROR_MORE_DATA);
2714 ret = FALSE;
2715 }
2716 else
2717 {
2718 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2719
2720 blob->cbData = dataLen;
2721 assert(blob->pbData);
2722 /* remove leading zero byte if it exists */
2723 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
2724 {
2725 blob->cbData--;
2726 blob->pbData++;
2727 }
2728 if (blob->cbData)
2729 {
2730 DWORD i;
2731
2732 for (i = 0; i < blob->cbData; i++)
2733 {
2734 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2735 dataLen - i - 1);
2736 }
2737 }
2738 }
2739 }
2740 }
2741 else
2742 {
2743 SetLastError(CRYPT_E_ASN1_BADTAG);
2744 ret = FALSE;
2745 }
2746 return ret;
2747 }
2748
2749 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
2750 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2751 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2752 {
2753 BOOL ret;
2754
2755 __TRY
2756 {
2757 DWORD bytesNeeded;
2758
2759 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2760 lpszStructType, pbEncoded, cbEncoded,
2761 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2762 {
2763 if (!pvStructInfo)
2764 *pcbStructInfo = bytesNeeded;
2765 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2766 pvStructInfo, pcbStructInfo, bytesNeeded)))
2767 {
2768 CRYPT_INTEGER_BLOB *blob;
2769
2770 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2771 pvStructInfo = *(BYTE **)pvStructInfo;
2772 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
2773 blob->pbData = (BYTE *)pvStructInfo +
2774 sizeof(CRYPT_INTEGER_BLOB);
2775 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
2776 lpszStructType, pbEncoded, cbEncoded,
2777 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
2778 &bytesNeeded);
2779 }
2780 }
2781 }
2782 __EXCEPT_PAGE_FAULT
2783 {
2784 SetLastError(STATUS_ACCESS_VIOLATION);
2785 ret = FALSE;
2786 }
2787 __ENDTRY
2788 return ret;
2789 }
2790
2791 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
2792 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2793 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2794 {
2795 BOOL ret;
2796
2797 if (!pvStructInfo)
2798 {
2799 *pcbStructInfo = sizeof(int);
2800 return TRUE;
2801 }
2802 __TRY
2803 {
2804 if (pbEncoded[0] == ASN_ENUMERATED)
2805 {
2806 unsigned int val = 0, i;
2807
2808 if (cbEncoded <= 1)
2809 {
2810 SetLastError(CRYPT_E_ASN1_EOD);
2811 ret = FALSE;
2812 }
2813 else if (pbEncoded[1] == 0)
2814 {
2815 SetLastError(CRYPT_E_ASN1_CORRUPT);
2816 ret = FALSE;
2817 }
2818 else
2819 {
2820 /* A little strange looking, but we have to accept a sign byte:
2821 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
2822 * assuming a small length is okay here, it has to be in short
2823 * form.
2824 */
2825 if (pbEncoded[1] > sizeof(unsigned int) + 1)
2826 {
2827 SetLastError(CRYPT_E_ASN1_LARGE);
2828 return FALSE;
2829 }
2830 for (i = 0; i < pbEncoded[1]; i++)
2831 {
2832 val <<= 8;
2833 val |= pbEncoded[2 + i];
2834 }
2835 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2836 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
2837 {
2838 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2839 pvStructInfo = *(BYTE **)pvStructInfo;
2840 memcpy(pvStructInfo, &val, sizeof(unsigned int));
2841 }
2842 }
2843 }
2844 else
2845 {
2846 SetLastError(CRYPT_E_ASN1_BADTAG);
2847 ret = FALSE;
2848 }
2849 }
2850 __EXCEPT_PAGE_FAULT
2851 {
2852 SetLastError(STATUS_ACCESS_VIOLATION);
2853 ret = FALSE;
2854 }
2855 __ENDTRY
2856 return ret;
2857 }
2858
2859 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
2860 * if it fails.
2861 */
2862 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
2863 do { \
2864 BYTE i; \
2865 \
2866 (word) = 0; \
2867 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
2868 { \
2869 if (!isdigit(*(pbEncoded))) \
2870 { \
2871 SetLastError(CRYPT_E_ASN1_CORRUPT); \
2872 ret = FALSE; \
2873 } \
2874 else \
2875 { \
2876 (word) *= 10; \
2877 (word) += *(pbEncoded)++ - '0'; \
2878 } \
2879 } \
2880 } while (0)
2881
2882 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
2883 SYSTEMTIME *sysTime)
2884 {
2885 BOOL ret;
2886
2887 __TRY
2888 {
2889 ret = TRUE;
2890 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
2891 {
2892 WORD hours, minutes = 0;
2893 BYTE sign = *pbEncoded++;
2894
2895 len--;
2896 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
2897 if (ret && hours >= 24)
2898 {
2899 SetLastError(CRYPT_E_ASN1_CORRUPT);
2900 ret = FALSE;
2901 }
2902 else if (len >= 2)
2903 {
2904 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
2905 if (ret && minutes >= 60)
2906 {
2907 SetLastError(CRYPT_E_ASN1_CORRUPT);
2908 ret = FALSE;
2909 }
2910 }
2911 if (ret)
2912 {
2913 if (sign == '+')
2914 {
2915 sysTime->wHour += hours;
2916 sysTime->wMinute += minutes;
2917 }
2918 else
2919 {
2920 if (hours > sysTime->wHour)
2921 {
2922 sysTime->wDay--;
2923 sysTime->wHour = 24 - (hours - sysTime->wHour);
2924 }
2925 else
2926 sysTime->wHour -= hours;
2927 if (minutes > sysTime->wMinute)
2928 {
2929 sysTime->wHour--;
2930 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
2931 }
2932 else
2933 sysTime->wMinute -= minutes;
2934 }
2935 }
2936 }
2937 }
2938 __EXCEPT_PAGE_FAULT
2939 {
2940 SetLastError(STATUS_ACCESS_VIOLATION);
2941 ret = FALSE;
2942 }
2943 __ENDTRY
2944 return ret;
2945 }
2946
2947 #define MIN_ENCODED_TIME_LENGTH 10
2948
2949 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
2950 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2951 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2952 {
2953 BOOL ret;
2954
2955 if (!pvStructInfo)
2956 {
2957 *pcbStructInfo = sizeof(FILETIME);
2958 return TRUE;
2959 }
2960 __TRY
2961 {
2962 ret = TRUE;
2963 if (pbEncoded[0] == ASN_UTCTIME)
2964 {
2965 if (cbEncoded <= 1)
2966 {
2967 SetLastError(CRYPT_E_ASN1_EOD);
2968 ret = FALSE;
2969 }
2970 else if (pbEncoded[1] > 0x7f)
2971 {
2972 /* long-form date strings really can't be valid */
2973 SetLastError(CRYPT_E_ASN1_CORRUPT);
2974 ret = FALSE;
2975 }
2976 else
2977 {
2978 SYSTEMTIME sysTime = { 0 };
2979 BYTE len = pbEncoded[1];
2980
2981 if (len < MIN_ENCODED_TIME_LENGTH)
2982 {
2983 SetLastError(CRYPT_E_ASN1_CORRUPT);
2984 ret = FALSE;
2985 }
2986 else
2987 {
2988 pbEncoded += 2;
2989 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
2990 if (sysTime.wYear >= 50)
2991 sysTime.wYear += 1900;
2992 else
2993 sysTime.wYear += 2000;
2994 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
2995 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
2996 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
2997 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
2998 if (ret && len > 0)
2999 {
3000 if (len >= 2 && isdigit(*pbEncoded) &&
3001 isdigit(*(pbEncoded + 1)))
3002 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3003 sysTime.wSecond);
3004 else if (isdigit(*pbEncoded))
3005 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3006 sysTime.wSecond);
3007 if (ret)
3008 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3009 &sysTime);
3010 }
3011 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3012 pDecodePara, pvStructInfo, pcbStructInfo,
3013 sizeof(FILETIME))))
3014 {
3015 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3016 pvStructInfo = *(BYTE **)pvStructInfo;
3017 ret = SystemTimeToFileTime(&sysTime,
3018 (FILETIME *)pvStructInfo);
3019 }
3020 }
3021 }
3022 }
3023 else
3024 {
3025 SetLastError(CRYPT_E_ASN1_BADTAG);
3026 ret = FALSE;
3027 }
3028 }
3029 __EXCEPT_PAGE_FAULT
3030 {
3031 SetLastError(STATUS_ACCESS_VIOLATION);
3032 ret = FALSE;
3033 }
3034 __ENDTRY
3035 return ret;
3036 }
3037
3038 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3039 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3040 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3041 {
3042 BOOL ret;
3043
3044 if (!pvStructInfo)
3045 {
3046 *pcbStructInfo = sizeof(FILETIME);
3047 return TRUE;
3048 }
3049 __TRY
3050 {
3051 ret = TRUE;
3052 if (pbEncoded[0] == ASN_GENERALTIME)
3053 {
3054 if (cbEncoded <= 1)
3055 {
3056 SetLastError(CRYPT_E_ASN1_EOD);
3057 ret = FALSE;
3058 }
3059 else if (pbEncoded[1] > 0x7f)
3060 {
3061 /* long-form date strings really can't be valid */
3062 SetLastError(CRYPT_E_ASN1_CORRUPT);
3063 ret = FALSE;
3064 }
3065 else
3066 {
3067 BYTE len = pbEncoded[1];
3068
3069 if (len < MIN_ENCODED_TIME_LENGTH)
3070 {
3071 SetLastError(CRYPT_E_ASN1_CORRUPT);
3072 ret = FALSE;
3073 }
3074 else
3075 {
3076 SYSTEMTIME sysTime = { 0 };
3077
3078 pbEncoded += 2;
3079 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3080 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3081 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3082 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3083 if (ret && len > 0)
3084 {
3085 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3086 sysTime.wMinute);
3087 if (ret && len > 0)
3088 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3089 sysTime.wSecond);
3090 if (ret && len > 0 && (*pbEncoded == '.' ||
3091 *pbEncoded == ','))
3092 {
3093 BYTE digits;
3094
3095 pbEncoded++;
3096 len--;
3097 /* workaround macro weirdness */
3098 digits = min(len, 3);
3099 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3100 sysTime.wMilliseconds);
3101 }
3102 if (ret)
3103 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3104 &sysTime);
3105 }
3106 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3107 pDecodePara, pvStructInfo, pcbStructInfo,
3108 sizeof(FILETIME))))
3109 {
3110 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3111 pvStructInfo = *(BYTE **)pvStructInfo;
3112 ret = SystemTimeToFileTime(&sysTime,
3113 (FILETIME *)pvStructInfo);
3114 }
3115 }
3116 }
3117 }
3118 else
3119 {
3120 SetLastError(CRYPT_E_ASN1_BADTAG);
3121 ret = FALSE;
3122 }
3123 }
3124 __EXCEPT_PAGE_FAULT
3125 {
3126 SetLastError(STATUS_ACCESS_VIOLATION);
3127 ret = FALSE;
3128 }
3129 __ENDTRY
3130 return ret;
3131 }
3132
3133 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3134 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3135 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3136 {
3137 BOOL ret;
3138
3139 __TRY
3140 {
3141 if (pbEncoded[0] == ASN_UTCTIME)
3142 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3143 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3144 pcbStructInfo);
3145 else if (pbEncoded[0] == ASN_GENERALTIME)
3146 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3147 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3148 pvStructInfo, pcbStructInfo);
3149 else
3150 {
3151 SetLastError(CRYPT_E_ASN1_BADTAG);
3152 ret = FALSE;
3153 }
3154 }
3155 __EXCEPT_PAGE_FAULT
3156 {
3157 SetLastError(STATUS_ACCESS_VIOLATION);
3158 ret = FALSE;
3159 }
3160 __ENDTRY
3161 return ret;
3162 }
3163
3164 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3165 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3166 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3167 {
3168 BOOL ret = TRUE;
3169
3170 __TRY
3171 {
3172 if (pbEncoded[0] == ASN_SEQUENCEOF)
3173 {
3174 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3175
3176 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3177 {
3178 BYTE lenBytes;
3179 const BYTE *ptr;
3180
3181 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3182 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3183 cValue = 0;
3184 ptr = pbEncoded + 1 + lenBytes;
3185 remainingLen = dataLen;
3186 while (ret && remainingLen)
3187 {
3188 DWORD nextLen;
3189
3190 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3191 if (ret)
3192 {
3193 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3194
3195 remainingLen -= 1 + nextLenBytes + nextLen;
3196 ptr += 1 + nextLenBytes + nextLen;
3197 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3198 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3199 bytesNeeded += 1 + nextLenBytes + nextLen;
3200 cValue++;
3201 }
3202 }
3203 if (ret)
3204 {
3205 CRYPT_SEQUENCE_OF_ANY *seq;
3206 BYTE *nextPtr;
3207 DWORD i;
3208
3209 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3210 pvStructInfo, pcbStructInfo, bytesNeeded)))
3211 {
3212 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3213 pvStructInfo = *(BYTE **)pvStructInfo;
3214 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3215 seq->cValue = cValue;
3216 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3217 sizeof(*seq));
3218 nextPtr = (BYTE *)seq->rgValue +
3219 cValue * sizeof(CRYPT_DER_BLOB);
3220 ptr = pbEncoded + 1 + lenBytes;
3221 remainingLen = dataLen;
3222 i = 0;
3223 while (ret && remainingLen)
3224 {
3225 DWORD nextLen;
3226
3227 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3228 if (ret)
3229 {
3230 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3231
3232 seq->rgValue[i].cbData = 1 + nextLenBytes +
3233 nextLen;
3234 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3235 seq->rgValue[i].pbData = (BYTE *)ptr;
3236 else
3237 {
3238 seq->rgValue[i].pbData = nextPtr;
3239 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3240 nextLen);
3241 nextPtr += 1 + nextLenBytes + nextLen;
3242 }
3243 remainingLen -= 1 + nextLenBytes + nextLen;
3244 ptr += 1 + nextLenBytes + nextLen;
3245 i++;
3246 }
3247 }
3248 }
3249 }
3250 }
3251 }
3252 else
3253 {
3254 SetLastError(CRYPT_E_ASN1_BADTAG);
3255 ret = FALSE;
3256 }
3257 }
3258 __EXCEPT_PAGE_FAULT
3259 {
3260 SetLastError(STATUS_ACCESS_VIOLATION);
3261 ret = FALSE;
3262 }
3263 __ENDTRY
3264 return ret;
3265 }
3266
3267 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3268 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3269 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3270 {
3271 BOOL ret;
3272
3273 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3274 {
3275 DWORD bytesNeeded, dataLen;
3276
3277 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3278 {
3279 struct AsnArrayDescriptor arrayDesc = {
3280 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3281 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3282 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3283 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3284
3285 if (dataLen)
3286 {
3287 DWORD nameLen;
3288
3289 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3290 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3291 0, NULL, NULL, &nameLen, NULL);
3292 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3293 }
3294 else
3295 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3296 if (!pvStructInfo)
3297 *pcbStructInfo = bytesNeeded;
3298 else if (*pcbStructInfo < bytesNeeded)
3299 {
3300 *pcbStructInfo = bytesNeeded;
3301 SetLastError(ERROR_MORE_DATA);
3302 ret = FALSE;
3303 }
3304 else
3305 {
3306 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3307
3308 if (dataLen)
3309 {
3310 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3311 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3312 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3313 0, NULL, &name->u.FullName, pcbStructInfo,
3314 name->u.FullName.rgAltEntry);
3315 }
3316 else
3317 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3318 }
3319 }
3320 }
3321 else
3322 {
3323 SetLastError(CRYPT_E_ASN1_BADTAG);
3324 ret = FALSE;
3325 }
3326 return ret;
3327 }
3328
3329 static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
3330 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3331 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3332 {
3333 struct AsnDecodeSequenceItem items[] = {
3334 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3335 DistPointName), CRYPT_AsnDecodeDistPointName,
3336 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3337 DistPointName.u.FullName.rgAltEntry), 0 },
3338 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3339 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3340 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3341 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3342 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3343 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3344 };
3345 BOOL ret;
3346
3347 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3348 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3349 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3350 return ret;
3351 }
3352
3353 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3354 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3355 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3356 {
3357 BOOL ret;
3358
3359 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3360 pDecodePara, pvStructInfo, *pcbStructInfo);
3361
3362 __TRY
3363 {
3364 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3365 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3366 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3367
3368 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3369 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3370 }
3371 __EXCEPT_PAGE_FAULT
3372 {
3373 SetLastError(STATUS_ACCESS_VIOLATION);
3374 ret = FALSE;
3375 }
3376 __ENDTRY
3377 return ret;
3378 }
3379
3380 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3381 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3382 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3383 {
3384 BOOL ret;
3385
3386 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3387 pDecodePara, pvStructInfo, *pcbStructInfo);
3388
3389 __TRY
3390 {
3391 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3392 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3393
3394 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3395 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3396 }
3397 __EXCEPT_PAGE_FAULT
3398 {
3399 SetLastError(STATUS_ACCESS_VIOLATION);
3400 ret = FALSE;
3401 }
3402 __ENDTRY
3403 return ret;
3404 }
3405
3406 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3407 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3408 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3409 {
3410 BOOL ret;
3411
3412 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3413 pDecodePara, pvStructInfo, *pcbStructInfo);
3414
3415 __TRY
3416 {
3417 struct AsnDecodeSequenceItem items[] = {
3418 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3419 DistPointName), CRYPT_AsnDecodeDistPointName,
3420 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3421 offsetof(CRL_ISSUING_DIST_POINT,
3422 DistPointName.u.FullName.rgAltEntry), 0 },
3423 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3424 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3425 FALSE, 0 },
3426 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3427 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3428 FALSE, 0 },
3429 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3430 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3431 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3432 OnlySomeReasonFlags.pbData), 0 },
3433 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3434 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3435 };
3436
3437 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3438 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3439 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3440 }
3441 __EXCEPT_PAGE_FAULT
3442 {
3443 SetLastError(STATUS_ACCESS_VIOLATION);
3444 ret = FALSE;
3445 }
3446 __ENDTRY
3447 return ret;
3448 }
3449
3450 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
3451 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3452 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3453 {
3454 static HCRYPTOIDFUNCSET set = NULL;
3455 BOOL ret = FALSE;
3456 CryptDecodeObjectExFunc decodeFunc = NULL;
3457 HCRYPTOIDFUNCADDR hFunc = NULL;
3458
3459 TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
3460 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
3461 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3462
3463 if (!pvStructInfo && !pcbStructInfo)
3464 {
3465 SetLastError(ERROR_INVALID_PARAMETER);
3466 return FALSE;
3467 }
3468 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
3469 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
3470 {
3471 SetLastError(ERROR_FILE_NOT_FOUND);
3472 return FALSE;
3473 }
3474 if (!cbEncoded)
3475 {
3476 SetLastError(CRYPT_E_ASN1_EOD);
3477 return FALSE;
3478 }
3479 if (cbEncoded > MAX_ENCODED_LEN)
3480 {
3481 SetLastError(CRYPT_E_ASN1_LARGE);
3482 return FALSE;
3483 }
3484
3485 SetLastError(NOERROR);
3486 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
3487 *(BYTE **)pvStructInfo = NULL;
3488 if (!HIWORD(lpszStructType))
3489 {
3490 switch (LOWORD(lpszStructType))
3491 {
3492 case (WORD)X509_CERT:
3493 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
3494 break;
3495 case (WORD)X509_CERT_TO_BE_SIGNED:
3496 decodeFunc = CRYPT_AsnDecodeCert;
3497 break;
3498 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
3499 decodeFunc = CRYPT_AsnDecodeCRL;
3500 break;
3501 case (WORD)X509_EXTENSIONS:
3502 decodeFunc = CRYPT_AsnDecodeExtensions;
3503 break;
3504 case (WORD)X509_NAME_VALUE:
3505 decodeFunc = CRYPT_AsnDecodeNameValue;
3506 break;
3507 case (WORD)X509_NAME:
3508 decodeFunc = CRYPT_AsnDecodeName;
3509 break;
3510 case (WORD)X509_PUBLIC_KEY_INFO:
3511 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
3512 break;
3513 case (WORD)X509_AUTHORITY_KEY_ID:
3514 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3515 break;
3516 case (WORD)X509_ALTERNATE_NAME:
3517 decodeFunc = CRYPT_AsnDecodeAltName;
3518 break;
3519 case (WORD)X509_BASIC_CONSTRAINTS:
3520 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3521 break;
3522 case (WORD)X509_BASIC_CONSTRAINTS2:
3523 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3524 break;
3525 case (WORD)RSA_CSP_PUBLICKEYBLOB:
3526 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
3527 break;
3528 case (WORD)X509_UNICODE_NAME:
3529 decodeFunc = CRYPT_AsnDecodeUnicodeName;
3530 break;
3531 case (WORD)X509_UNICODE_NAME_VALUE:
3532 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
3533 break;
3534 case (WORD)X509_OCTET_STRING:
3535 decodeFunc = CRYPT_AsnDecodeOctets;
3536 break;
3537 case (WORD)X509_BITS:
3538 case (WORD)X509_KEY_USAGE:
3539 decodeFunc = CRYPT_AsnDecodeBits;
3540 break;
3541 case (WORD)X509_INTEGER:
3542 decodeFunc = CRYPT_AsnDecodeInt;
3543 break;
3544 case (WORD)X509_MULTI_BYTE_INTEGER:
3545 decodeFunc = CRYPT_AsnDecodeInteger;
3546 break;
3547 case (WORD)X509_MULTI_BYTE_UINT:
3548 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
3549 break;
3550 case (WORD)X509_ENUMERATED:
3551 decodeFunc = CRYPT_AsnDecodeEnumerated;
3552 break;
3553 case (WORD)X509_CHOICE_OF_TIME:
3554 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
3555 break;
3556 case (WORD)X509_SEQUENCE_OF_ANY:
3557 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
3558 break;
3559 case (WORD)PKCS_UTC_TIME:
3560 decodeFunc = CRYPT_AsnDecodeUtcTime;
3561 break;
3562 case (WORD)X509_CRL_DIST_POINTS:
3563 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3564 break;
3565 case (WORD)X509_ENHANCED_KEY_USAGE:
3566 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3567 break;
3568 case (WORD)X509_ISSUING_DIST_POINT:
3569 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3570 break;
3571 default:
3572 FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
3573 }
3574 }
3575 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
3576 decodeFunc = CRYPT_AsnDecodeExtensions;
3577 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
3578 decodeFunc = CRYPT_AsnDecodeUtcTime;
3579 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
3580 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
3581 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
3582 decodeFunc = CRYPT_AsnDecodeEnumerated;
3583 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
3584 decodeFunc = CRYPT_AsnDecodeBits;
3585 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
3586 decodeFunc = CRYPT_AsnDecodeOctets;
3587 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
3588 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
3589 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
3590 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
3591 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
3592 decodeFunc = CRYPT_AsnDecodeAltName;
3593 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
3594 decodeFunc = CRYPT_AsnDecodeAltName;
3595 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
3596 decodeFunc = CRYPT_AsnDecodeAltName;
3597 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
3598 decodeFunc = CRYPT_AsnDecodeAltName;
3599 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
3600 decodeFunc = CRYPT_AsnDecodeAltName;
3601 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
3602 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
3603 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
3604 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
3605 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
3606 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
3607 else
3608 TRACE("OID %s not found or unimplemented, looking for DLL\n",
3609 debugstr_a(lpszStructType));
3610 if (!decodeFunc)
3611 {
3612 if (!set)
3613 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
3614 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
3615 (void **)&decodeFunc, &hFunc);
3616 }
3617 if (decodeFunc)
3618 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
3619 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
3620 else
3621 SetLastError(ERROR_FILE_NOT_FOUND);
3622 if (hFunc)
3623 CryptFreeOIDFunctionAddress(hFunc, 0);
3624 return ret;
3625 }