~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/crypt32/decode.c

Version: ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  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