1 /*
2 * Copyright 2005-2007 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 isn't
21 * implemented, 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 "Constants for CryptEncodeObject and CryptDecodeObject"
31 */
32
33 #include "config.h"
34 #include "wine/port.h"
35
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40
41 #define NONAMELESSUNION
42
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "winnls.h"
47 #include "snmp.h"
48 #include "wine/debug.h"
49 #include "wine/exception.h"
50 #include "crypt32_private.h"
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(cryptasn);
59 WINE_DECLARE_DEBUG_CHANNEL(crypt);
60
61 struct GenericArray
62 {
63 DWORD cItems;
64 BYTE *rgItems;
65 };
66
67 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
68 DWORD, DWORD, void *, DWORD *);
69 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
70 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
71
72 /* Internal decoders don't do memory allocation or exception handling, and
73 * they report how many bytes they decoded.
74 */
75 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
76 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
77
78 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
79 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
80 DWORD *pcbDecoded);
81 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
82 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
83 DWORD *pcbDecoded);
84 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
85 * time, doesn't do memory allocation, and doesn't do exception handling.
86 */
87 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
88 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
89 DWORD *pcbDecoded);
90 /* Assumes algo->Parameters.pbData is set ahead of time. */
91 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
92 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
93 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
94 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
97 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
98 DWORD *pcbDecoded);
99 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
100 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
101 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
102 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
103 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
104 * member has been initialized, doesn't do exception handling, and doesn't do
105 * memory allocation. Also doesn't check tag, assumes the caller has checked
106 * it.
107 */
108 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
109 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
110 DWORD *pcbDecoded);
111 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
112 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
113 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
114 DWORD *pcbDecoded);
115
116 /* Gets the number of length bytes from the given (leading) length byte */
117 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
118
119 /* Helper function to get the encoded length of the data starting at pbEncoded,
120 * where pbEncoded[0] is the tag. If the data are too short to contain a
121 * length or if the length is too large for cbEncoded, sets an appropriate
122 * error code and returns FALSE. If the encoded length is unknown due to
123 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
124 */
125 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
126 DWORD *len)
127 {
128 BOOL ret;
129
130 if (cbEncoded <= 1)
131 {
132 SetLastError(CRYPT_E_ASN1_CORRUPT);
133 ret = FALSE;
134 }
135 else if (pbEncoded[1] <= 0x7f)
136 {
137 if (pbEncoded[1] + 1 > cbEncoded)
138 {
139 SetLastError(CRYPT_E_ASN1_EOD);
140 ret = FALSE;
141 }
142 else
143 {
144 *len = pbEncoded[1];
145 ret = TRUE;
146 }
147 }
148 else if (pbEncoded[1] == 0x80)
149 {
150 *len = CMSG_INDEFINITE_LENGTH;
151 ret = TRUE;
152 }
153 else
154 {
155 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
156
157 if (lenLen > sizeof(DWORD) + 1)
158 {
159 SetLastError(CRYPT_E_ASN1_LARGE);
160 ret = FALSE;
161 }
162 else if (lenLen + 2 > cbEncoded)
163 {
164 SetLastError(CRYPT_E_ASN1_CORRUPT);
165 ret = FALSE;
166 }
167 else
168 {
169 DWORD out = 0;
170
171 pbEncoded += 2;
172 while (--lenLen)
173 {
174 out <<= 8;
175 out |= *pbEncoded++;
176 }
177 if (out + lenLen + 1 > cbEncoded)
178 {
179 SetLastError(CRYPT_E_ASN1_EOD);
180 ret = FALSE;
181 }
182 else
183 {
184 *len = out;
185 ret = TRUE;
186 }
187 }
188 }
189 return ret;
190 }
191
192 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
193 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
194 {
195 BOOL ret;
196
197 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
198 *len == CMSG_INDEFINITE_LENGTH)
199 {
200 SetLastError(CRYPT_E_ASN1_CORRUPT);
201 ret = FALSE;
202 }
203 return ret;
204 }
205
206 /* Helper function to check *pcbStructInfo, set it to the required size, and
207 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
208 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
209 * pointer to the newly allocated memory.
210 */
211 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
212 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
213 DWORD bytesNeeded)
214 {
215 BOOL ret = TRUE;
216
217 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
218 {
219 if (pDecodePara && pDecodePara->pfnAlloc)
220 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
221 else
222 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
223 if (!*(BYTE **)pvStructInfo)
224 ret = FALSE;
225 else
226 *pcbStructInfo = bytesNeeded;
227 }
228 else if (*pcbStructInfo < bytesNeeded)
229 {
230 *pcbStructInfo = bytesNeeded;
231 SetLastError(ERROR_MORE_DATA);
232 ret = FALSE;
233 }
234 return ret;
235 }
236
237 static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
238 {
239 if (pDecodePara && pDecodePara->pfnFree)
240 pDecodePara->pfnFree(pv);
241 else
242 LocalFree(pv);
243 }
244
245 /* Helper function to check *pcbStructInfo and set it to the required size.
246 * Assumes pvStructInfo is not NULL.
247 */
248 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
249 {
250 BOOL ret;
251
252 if (*pcbStructInfo < bytesNeeded)
253 {
254 *pcbStructInfo = bytesNeeded;
255 SetLastError(ERROR_MORE_DATA);
256 ret = FALSE;
257 }
258 else
259 {
260 *pcbStructInfo = bytesNeeded;
261 ret = TRUE;
262 }
263 return ret;
264 }
265
266 /* tag:
267 * The expected tag of the item. If tag is 0, decodeFunc is called
268 * regardless of the tag value seen.
269 * offset:
270 * A sequence is decoded into a struct. The offset member is the
271 * offset of this item within that struct.
272 * decodeFunc:
273 * The decoder function to use. If this is NULL, then the member isn't
274 * decoded, but minSize space is reserved for it.
275 * minSize:
276 * The minimum amount of space occupied after decoding. You must set this.
277 * optional:
278 * If true, and the tag doesn't match the expected tag for this item,
279 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
280 * filled with 0 for this member.
281 * hasPointer, pointerOffset:
282 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
283 * the offset within the struct of the data pointer (or to the
284 * first data pointer, if more than one exist).
285 * size:
286 * Used by CRYPT_AsnDecodeSequence, not for your use.
287 */
288 struct AsnDecodeSequenceItem
289 {
290 BYTE tag;
291 DWORD offset;
292 InternalDecodeFunc decodeFunc;
293 DWORD minSize;
294 BOOL optional;
295 BOOL hasPointer;
296 DWORD pointerOffset;
297 DWORD size;
298 };
299
300 /* Decodes the items in a sequence, where the items are described in items,
301 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
302 * pvStructInfo. nextData is a pointer to the memory location at which the
303 * first decoded item with a dynamic pointer should point.
304 * Upon decoding, *cbDecoded is the total number of bytes decoded.
305 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
306 */
307 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
308 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
309 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
310 {
311 BOOL ret;
312 DWORD i, decoded = 0;
313 const BYTE *ptr = pbEncoded;
314
315 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
316 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
317
318 for (i = 0, ret = TRUE; ret && i < cItem; i++)
319 {
320 if (cbEncoded - (ptr - pbEncoded) != 0)
321 {
322 DWORD itemLen;
323
324 if ((ret = CRYPT_GetLengthIndefinite(ptr,
325 cbEncoded - (ptr - pbEncoded), &itemLen)))
326 {
327 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
328
329 if (ptr[0] == items[i].tag || !items[i].tag)
330 {
331 DWORD itemEncodedLen;
332
333 if (itemLen == CMSG_INDEFINITE_LENGTH)
334 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
335 else
336 itemEncodedLen = 1 + itemLenBytes + itemLen;
337 if (nextData && pvStructInfo && items[i].hasPointer)
338 {
339 TRACE("Setting next pointer to %p\n",
340 nextData);
341 *(BYTE **)((BYTE *)pvStructInfo +
342 items[i].pointerOffset) = nextData;
343 }
344 if (items[i].decodeFunc)
345 {
346 DWORD itemDecoded;
347
348 if (pvStructInfo)
349 TRACE("decoding item %d\n", i);
350 else
351 TRACE("sizing item %d\n", i);
352 ret = items[i].decodeFunc(ptr, itemEncodedLen,
353 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
354 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
355 : NULL, &items[i].size, &itemDecoded);
356 if (ret)
357 {
358 /* Account for alignment padding */
359 if (items[i].size % sizeof(DWORD_PTR))
360 items[i].size += sizeof(DWORD_PTR) -
361 items[i].size % sizeof(DWORD_PTR);
362 TRACE("item %d size: %d\n", i, items[i].size);
363 if (nextData && items[i].hasPointer &&
364 items[i].size > items[i].minSize)
365 nextData += items[i].size - items[i].minSize;
366 if (itemDecoded > itemEncodedLen)
367 {
368 WARN("decoded length %d exceeds encoded %d\n",
369 itemDecoded, itemEncodedLen);
370 SetLastError(CRYPT_E_ASN1_CORRUPT);
371 ret = FALSE;
372 }
373 else
374 {
375 if (itemLen == CMSG_INDEFINITE_LENGTH)
376 {
377 if (itemDecoded > itemEncodedLen - 2 ||
378 *(ptr + itemDecoded) != 0 ||
379 *(ptr + itemDecoded + 1) != 0)
380 {
381 TRACE("expected 0 TLV\n");
382 SetLastError(CRYPT_E_ASN1_CORRUPT);
383 ret = FALSE;
384 }
385 else
386 itemDecoded += 2;
387 }
388 if (ret)
389 {
390 ptr += itemDecoded;
391 decoded += itemDecoded;
392 TRACE("item %d: decoded %d bytes\n", i,
393 itemDecoded);
394 }
395 }
396 }
397 else if (items[i].optional &&
398 GetLastError() == CRYPT_E_ASN1_BADTAG)
399 {
400 TRACE("skipping optional item %d\n", i);
401 items[i].size = items[i].minSize;
402 SetLastError(NOERROR);
403 ret = TRUE;
404 }
405 else
406 TRACE("item %d failed: %08x\n", i,
407 GetLastError());
408 }
409 else if (itemLen == CMSG_INDEFINITE_LENGTH)
410 {
411 ERR("can't use indefinite length encoding without a decoder\n");
412 SetLastError(CRYPT_E_ASN1_CORRUPT);
413 ret = FALSE;
414 }
415 else
416 {
417 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
418 ptr += itemEncodedLen;
419 decoded += itemEncodedLen;
420 items[i].size = items[i].minSize;
421 }
422 }
423 else if (items[i].optional)
424 {
425 TRACE("skipping optional item %d\n", i);
426 items[i].size = items[i].minSize;
427 }
428 else
429 {
430 TRACE("item %d: tag %02x doesn't match expected %02x\n",
431 i, ptr[0], items[i].tag);
432 SetLastError(CRYPT_E_ASN1_BADTAG);
433 ret = FALSE;
434 }
435 }
436 }
437 else if (items[i].optional)
438 {
439 TRACE("missing optional item %d, skipping\n", i);
440 items[i].size = items[i].minSize;
441 }
442 else
443 {
444 TRACE("not enough bytes for item %d, failing\n", i);
445 SetLastError(CRYPT_E_ASN1_CORRUPT);
446 ret = FALSE;
447 }
448 }
449 if (cbDecoded)
450 *cbDecoded = decoded;
451 TRACE("returning %d\n", ret);
452 return ret;
453 }
454
455 /* This decodes an arbitrary sequence into a contiguous block of memory
456 * (basically, a struct.) Each element being decoded is described by a struct
457 * AsnDecodeSequenceItem, see above.
458 * startingPointer is an optional pointer to the first place where dynamic
459 * data will be stored. If you know the starting offset, you may pass it
460 * here. Otherwise, pass NULL, and one will be inferred from the items.
461 */
462 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
463 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
464 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
465 DWORD *pcbDecoded, void *startingPointer)
466 {
467 BOOL ret;
468
469 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
470 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
471 startingPointer);
472
473 if (pbEncoded[0] == ASN_SEQUENCE)
474 {
475 DWORD dataLen;
476
477 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
478 {
479 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
480 const BYTE *ptr = pbEncoded + 1 + lenBytes;
481 BOOL indefinite = FALSE;
482
483 cbEncoded -= 1 + lenBytes;
484 if (dataLen == CMSG_INDEFINITE_LENGTH)
485 {
486 dataLen = cbEncoded;
487 indefinite = TRUE;
488 }
489 else if (cbEncoded < dataLen)
490 {
491 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
492 cbEncoded);
493 SetLastError(CRYPT_E_ASN1_CORRUPT);
494 ret = FALSE;
495 }
496 if (ret)
497 {
498 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
499 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
500 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
501 {
502 if (cbDecoded > cbEncoded - 2)
503 {
504 /* Not enough space for 0 TLV */
505 SetLastError(CRYPT_E_ASN1_CORRUPT);
506 ret = FALSE;
507 }
508 else if (*(ptr + cbDecoded) != 0 ||
509 *(ptr + cbDecoded + 1) != 0)
510 {
511 TRACE("expected 0 TLV\n");
512 SetLastError(CRYPT_E_ASN1_CORRUPT);
513 ret = FALSE;
514 }
515 else
516 cbDecoded += 2;
517 }
518 }
519 if (ret && !indefinite && cbDecoded != dataLen)
520 {
521 TRACE("expected %d decoded, got %d, failing\n", dataLen,
522 cbDecoded);
523 SetLastError(CRYPT_E_ASN1_CORRUPT);
524 ret = FALSE;
525 }
526 if (ret)
527 {
528 DWORD i, bytesNeeded = 0, structSize = 0;
529
530 for (i = 0; i < cItem; i++)
531 {
532 bytesNeeded += items[i].size;
533 structSize += items[i].minSize;
534 }
535 if (pcbDecoded)
536 *pcbDecoded = 1 + lenBytes + cbDecoded;
537 if (!pvStructInfo)
538 *pcbStructInfo = bytesNeeded;
539 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
540 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
541 {
542 BYTE *nextData;
543
544 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
545 pvStructInfo = *(BYTE **)pvStructInfo;
546 if (startingPointer)
547 nextData = (BYTE *)startingPointer;
548 else
549 nextData = (BYTE *)pvStructInfo + structSize;
550 memset(pvStructInfo, 0, structSize);
551 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
552 ptr, dataLen, dwFlags, pvStructInfo, nextData,
553 &cbDecoded);
554 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
555 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
556 }
557 }
558 }
559 }
560 else
561 {
562 SetLastError(CRYPT_E_ASN1_BADTAG);
563 ret = FALSE;
564 }
565 TRACE("returning %d (%08x)\n", ret, GetLastError());
566 return ret;
567 }
568
569 /* tag:
570 * The expected tag of the entire encoded array (usually a variant
571 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
572 * regardless of the tag seen.
573 * decodeFunc:
574 * used to decode each item in the array
575 * itemSize:
576 * is the minimum size of each decoded item
577 * hasPointer:
578 * indicates whether each item has a dynamic pointer
579 * pointerOffset:
580 * indicates the offset within itemSize at which the pointer exists
581 */
582 struct AsnArrayDescriptor
583 {
584 BYTE tag;
585 InternalDecodeFunc decodeFunc;
586 DWORD itemSize;
587 BOOL hasPointer;
588 DWORD pointerOffset;
589 };
590
591 struct AsnArrayItemSize
592 {
593 DWORD encodedLen;
594 DWORD size;
595 };
596
597 /* Decodes an array of like types into a struct GenericArray.
598 * The layout and decoding of the array are described by a struct
599 * AsnArrayDescriptor.
600 */
601 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
602 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
603 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
604 DWORD *pcbDecoded, void *startingPointer)
605 {
606 BOOL ret = TRUE;
607
608 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
609 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
610 startingPointer);
611
612 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
613 {
614 DWORD dataLen;
615
616 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
617 {
618 DWORD bytesNeeded, cItems = 0, decoded;
619 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
620 /* There can be arbitrarily many items, but there is often only one.
621 */
622 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
623
624 decoded = 1 + lenBytes;
625 bytesNeeded = sizeof(struct GenericArray);
626 if (dataLen)
627 {
628 const BYTE *ptr;
629 BOOL doneDecoding = FALSE;
630
631 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
632 {
633 if (dataLen == CMSG_INDEFINITE_LENGTH)
634 {
635 if (ptr[0] == 0)
636 {
637 doneDecoding = TRUE;
638 if (ptr[1] != 0)
639 {
640 SetLastError(CRYPT_E_ASN1_CORRUPT);
641 ret = FALSE;
642 }
643 else
644 decoded += 2;
645 }
646 }
647 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
648 doneDecoding = TRUE;
649 if (!doneDecoding)
650 {
651 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
652
653 /* Each item decoded may not tolerate extraneous bytes,
654 * so get the length of the next element if known.
655 */
656 if ((ret = CRYPT_GetLengthIndefinite(ptr,
657 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
658 {
659 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
660 itemEncoded = cbEncoded - (ptr - pbEncoded);
661 else
662 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
663 itemDataLen;
664 }
665 if (ret)
666 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
667 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
668 &itemDecoded);
669 if (ret)
670 {
671 cItems++;
672 if (itemSizes != &itemSize)
673 itemSizes = CryptMemRealloc(itemSizes,
674 cItems * sizeof(struct AsnArrayItemSize));
675 else if (cItems > 1)
676 {
677 itemSizes =
678 CryptMemAlloc(
679 cItems * sizeof(struct AsnArrayItemSize));
680 if (itemSizes)
681 memcpy(itemSizes, &itemSize,
682 sizeof(itemSize));
683 }
684 if (itemSizes)
685 {
686 decoded += itemDecoded;
687 itemSizes[cItems - 1].encodedLen = itemEncoded;
688 itemSizes[cItems - 1].size = size;
689 bytesNeeded += size;
690 ptr += itemEncoded;
691 }
692 else
693 ret = FALSE;
694 }
695 }
696 }
697 }
698 if (ret)
699 {
700 if (pcbDecoded)
701 *pcbDecoded = decoded;
702 if (!pvStructInfo)
703 *pcbStructInfo = bytesNeeded;
704 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
705 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
706 {
707 DWORD i;
708 BYTE *nextData;
709 const BYTE *ptr;
710 struct GenericArray *array;
711
712 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
713 pvStructInfo = *(BYTE **)pvStructInfo;
714 array = (struct GenericArray *)pvStructInfo;
715 array->cItems = cItems;
716 if (startingPointer)
717 array->rgItems = startingPointer;
718 else
719 array->rgItems = (BYTE *)array +
720 sizeof(struct GenericArray);
721 nextData = array->rgItems +
722 array->cItems * arrayDesc->itemSize;
723 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
724 i < cItems && ptr - pbEncoded - 1 - lenBytes <
725 dataLen; i++)
726 {
727 DWORD itemDecoded;
728
729 if (arrayDesc->hasPointer)
730 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
731 + arrayDesc->pointerOffset) = nextData;
732 ret = arrayDesc->decodeFunc(ptr,
733 itemSizes[i].encodedLen,
734 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
735 array->rgItems + i * arrayDesc->itemSize,
736 &itemSizes[i].size, &itemDecoded);
737 if (ret)
738 {
739 nextData += itemSizes[i].size - arrayDesc->itemSize;
740 ptr += itemDecoded;
741 }
742 }
743 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
744 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
745 }
746 }
747 if (itemSizes != &itemSize)
748 CryptMemFree(itemSizes);
749 }
750 }
751 else
752 {
753 SetLastError(CRYPT_E_ASN1_BADTAG);
754 ret = FALSE;
755 }
756 return ret;
757 }
758
759 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
760 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
761 * to CRYPT_E_ASN1_CORRUPT.
762 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
763 * set!
764 */
765 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
766 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
767 {
768 BOOL ret;
769 DWORD dataLen;
770
771 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
772 {
773 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
774 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
775
776 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
777 bytesNeeded += 1 + lenBytes + dataLen;
778
779 if (pcbDecoded)
780 *pcbDecoded = 1 + lenBytes + dataLen;
781 if (!pvStructInfo)
782 *pcbStructInfo = bytesNeeded;
783 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
784 {
785 CRYPT_DER_BLOB *blob;
786
787 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
788 pvStructInfo = *(BYTE **)pvStructInfo;
789 blob = (CRYPT_DER_BLOB *)pvStructInfo;
790 blob->cbData = 1 + lenBytes + dataLen;
791 if (blob->cbData)
792 {
793 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
794 blob->pbData = (BYTE *)pbEncoded;
795 else
796 {
797 assert(blob->pbData);
798 memcpy(blob->pbData, pbEncoded, blob->cbData);
799 }
800 }
801 else
802 {
803 SetLastError(CRYPT_E_ASN1_CORRUPT);
804 ret = FALSE;
805 }
806 }
807 }
808 return ret;
809 }
810
811 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
812 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
813 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
814 DWORD *pcbDecoded)
815 {
816 BOOL ret;
817
818 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
819 pvStructInfo, *pcbStructInfo, pcbDecoded);
820
821 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
822 * place.
823 */
824 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
825 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
826 pcbDecoded);
827 if (ret && pvStructInfo)
828 {
829 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
830
831 if (blob->cbData)
832 {
833 DWORD i;
834 BYTE temp;
835
836 for (i = 0; i < blob->cbData / 2; i++)
837 {
838 temp = blob->pbData[i];
839 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
840 blob->pbData[blob->cbData - i - 1] = temp;
841 }
842 }
843 }
844 TRACE("returning %d (%08x)\n", ret, GetLastError());
845 return ret;
846 }
847
848 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
849 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
850 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
851 {
852 BOOL ret = TRUE;
853
854 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
855 pDecodePara, pvStructInfo, *pcbStructInfo);
856
857 __TRY
858 {
859 struct AsnDecodeSequenceItem items[] = {
860 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
861 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
862 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
863 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
864 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
865 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
866 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
867 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
868 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
869 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
870 };
871
872 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
873 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
874 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
875 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
876 pcbStructInfo, NULL, NULL);
877 }
878 __EXCEPT_PAGE_FAULT
879 {
880 SetLastError(STATUS_ACCESS_VIOLATION);
881 ret = FALSE;
882 }
883 __ENDTRY
884
885 TRACE("Returning %d (%08x)\n", ret, GetLastError());
886 return ret;
887 }
888
889 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
890 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
891 {
892 BOOL ret;
893 DWORD dataLen;
894
895 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
896 {
897 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
898
899 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
900 dwFlags, pvStructInfo, pcbStructInfo, NULL);
901 if (pcbDecoded)
902 *pcbDecoded = 1 + lenBytes + dataLen;
903 }
904 return ret;
905 }
906
907 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
908 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
909 {
910 BOOL ret;
911
912 struct AsnDecodeSequenceItem items[] = {
913 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
914 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
915 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
916 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
917 };
918
919 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
920 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
921 pcbDecoded, NULL);
922 return ret;
923 }
924
925 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
926 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
927 DWORD *pcbDecoded)
928 {
929 BOOL ret;
930 DWORD dataLen;
931
932 if ((ret = CRYP