wined3d: Rename CreateAdditionalSwapChain to CreateSwapChain.
[wine] / dlls / wintrust / asn.c
1 /* wintrust asn functions
2  *
3  * Copyright 2007 Juan Lang
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  *
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <assert.h>
27 #define NONAMELESSUNION
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winerror.h"
31 #include "wincrypt.h"
32 #include "wintrust.h"
33 #include "snmp.h"
34 #include "winternl.h"
35 #include "wine/debug.h"
36 #include "wine/exception.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
39
40 #ifdef WORDS_BIGENDIAN
41
42 #define hton16(x) (x)
43 #define n16toh(x) (x)
44
45 #else
46
47 #define hton16(x) RtlUshortByteSwap(x)
48 #define n16toh(x) RtlUshortByteSwap(x)
49
50 #endif
51
52 #define ASN_BITSTRING       (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
53 #define ASN_BMPSTRING       (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1e)
54
55 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
56 {
57     DWORD bytesNeeded, significantBytes = 0;
58
59     if (len <= 0x7f)
60         bytesNeeded = 1;
61     else
62     {
63         DWORD temp;
64
65         for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
66          temp <<= 8, significantBytes--)
67             ;
68         bytesNeeded = significantBytes + 1;
69     }
70     if (!pbEncoded)
71     {
72         *pcbEncoded = bytesNeeded;
73         return TRUE;
74     }
75     if (*pcbEncoded < bytesNeeded)
76     {
77         SetLastError(ERROR_MORE_DATA);
78         return FALSE;
79     }
80     if (len <= 0x7f)
81         *pbEncoded = (BYTE)len;
82     else
83     {
84         DWORD i;
85
86         *pbEncoded++ = significantBytes | 0x80;
87         for (i = 0; i < significantBytes; i++)
88         {
89             *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
90             len >>= 8;
91         }
92     }
93     *pcbEncoded = bytesNeeded;
94     return TRUE;
95 }
96
97 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
98  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
99  DWORD *pcbEncoded)
100 {
101     BOOL ret = TRUE;
102     const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
103     DWORD bytesNeeded, lenBytes;
104
105     TRACE("(%d, %p), %p, %d\n", blob->cbData, blob->pbData, pbEncoded,
106      *pcbEncoded);
107
108     CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
109     bytesNeeded = 1 + lenBytes + blob->cbData;
110     if (!pbEncoded)
111         *pcbEncoded = bytesNeeded;
112     else if (*pcbEncoded < bytesNeeded)
113     {
114         *pcbEncoded = bytesNeeded;
115         SetLastError(ERROR_MORE_DATA);
116         ret = FALSE;
117     }
118     else
119     {
120         *pbEncoded++ = ASN_OCTETSTRING;
121         CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
122         pbEncoded += lenBytes;
123         if (blob->cbData)
124             memcpy(pbEncoded, blob->pbData, blob->cbData);
125     }
126     TRACE("returning %d\n", ret);
127     return ret;
128 }
129
130 BOOL WINAPI WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType,
131  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
132  DWORD *pcbEncoded)
133 {
134     BOOL ret = FALSE;
135
136     TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
137      debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
138      pcbEncoded);
139
140     __TRY
141     {
142         const SPC_LINK *link = (const SPC_LINK *)pvStructInfo;
143         DWORD bytesNeeded, lenBytes;
144
145         switch (link->dwLinkChoice)
146         {
147         case SPC_FILE_LINK_CHOICE:
148         {
149             DWORD fileNameLen, fileNameLenBytes;
150             LPWSTR ptr;
151
152             fileNameLen = link->u.pwszFile ?
153              lstrlenW(link->u.pwszFile) * sizeof(WCHAR) : 0;
154             CRYPT_EncodeLen(fileNameLen, NULL, &fileNameLenBytes);
155             CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, NULL,
156              &lenBytes);
157             bytesNeeded = 2 + lenBytes + fileNameLenBytes + fileNameLen;
158             if (!pbEncoded)
159             {
160                 *pcbEncoded = bytesNeeded;
161                 ret = TRUE;
162             }
163             else if (*pcbEncoded < bytesNeeded)
164             {
165                 SetLastError(ERROR_MORE_DATA);
166                 *pcbEncoded = bytesNeeded;
167             }
168             else
169             {
170                 *pcbEncoded = bytesNeeded;
171                 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 2;
172                 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, pbEncoded,
173                  &lenBytes);
174                 pbEncoded += lenBytes;
175                 *pbEncoded++ = ASN_CONTEXT;
176                 CRYPT_EncodeLen(fileNameLen, pbEncoded, &fileNameLenBytes);
177                 pbEncoded += fileNameLenBytes;
178                 for (ptr = link->u.pwszFile; ptr && *ptr; ptr++)
179                 {
180                     *(WCHAR *)pbEncoded = hton16(*ptr);
181                     pbEncoded += sizeof(WCHAR);
182                 }
183                 ret = TRUE;
184             }
185             break;
186         }
187         case SPC_MONIKER_LINK_CHOICE:
188         {
189             DWORD classIdLenBytes, dataLenBytes, dataLen;
190             CRYPT_DATA_BLOB classId = { sizeof(link->u.Moniker.ClassId),
191              (BYTE *)link->u.Moniker.ClassId };
192
193             CRYPT_EncodeLen(classId.cbData, NULL, &classIdLenBytes);
194             CRYPT_EncodeLen(link->u.Moniker.SerializedData.cbData, NULL,
195              &dataLenBytes);
196             dataLen = 2 + classIdLenBytes + classId.cbData +
197              dataLenBytes + link->u.Moniker.SerializedData.cbData;
198             CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
199             bytesNeeded = 1 + dataLen + lenBytes;
200             if (!pbEncoded)
201             {
202                 *pcbEncoded = bytesNeeded;
203                 ret = TRUE;
204             }
205             else if (*pcbEncoded < bytesNeeded)
206             {
207                 SetLastError(ERROR_MORE_DATA);
208                 *pcbEncoded = bytesNeeded;
209             }
210             else
211             {
212                 DWORD size;
213
214                 *pcbEncoded = bytesNeeded;
215                 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
216                 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
217                 pbEncoded += lenBytes;
218                 size = 1 + classIdLenBytes + classId.cbData;
219                 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL, &classId,
220                  pbEncoded, &size);
221                 pbEncoded += size;
222                 size = 1 + dataLenBytes + link->u.Moniker.SerializedData.cbData;
223                 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL,
224                  &link->u.Moniker.SerializedData, pbEncoded, &size);
225                 pbEncoded += size;
226                 ret = TRUE;
227             }
228             break;
229         }
230         case SPC_URL_LINK_CHOICE:
231         {
232             LPWSTR ptr;
233             DWORD urlLen;
234
235             /* Check for invalid characters in URL */
236             ret = TRUE;
237             urlLen = 0;
238             for (ptr = link->u.pwszUrl; ptr && *ptr && ret; ptr++)
239                 if (*ptr > 0x7f)
240                 {
241                     *pcbEncoded = 0;
242                     SetLastError(CRYPT_E_INVALID_IA5_STRING);
243                     ret = FALSE;
244                 }
245                 else
246                     urlLen++;
247             if (ret)
248             {
249                 CRYPT_EncodeLen(urlLen, NULL, &lenBytes);
250                 bytesNeeded = 1 + lenBytes + urlLen;
251                 if (!pbEncoded)
252                     *pcbEncoded = bytesNeeded;
253                 else if (*pcbEncoded < bytesNeeded)
254                 {
255                     SetLastError(ERROR_MORE_DATA);
256                     *pcbEncoded = bytesNeeded;
257                     ret = FALSE;
258                 }
259                 else
260                 {
261                     *pcbEncoded = bytesNeeded;
262                     *pbEncoded++ = ASN_CONTEXT;
263                     CRYPT_EncodeLen(urlLen, pbEncoded, &lenBytes);
264                     pbEncoded += lenBytes;
265                     for (ptr = link->u.pwszUrl; ptr && *ptr; ptr++)
266                         *pbEncoded++ = (BYTE)*ptr;
267                 }
268             }
269             break;
270         }
271         default:
272             SetLastError(E_INVALIDARG);
273         }
274     }
275     __EXCEPT_PAGE_FAULT
276     {
277         SetLastError(STATUS_ACCESS_VIOLATION);
278     }
279     __ENDTRY
280     TRACE("returning %d\n", ret);
281     return ret;
282 }
283
284 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
285  BYTE *, DWORD *);
286
287 struct AsnEncodeSequenceItem
288 {
289     const void           *pvStructInfo;
290     CryptEncodeObjectFunc encodeFunc;
291     DWORD                 size; /* used during encoding, not for your use */
292 };
293
294 static BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
295  struct AsnEncodeSequenceItem items[], DWORD cItem, BYTE *pbEncoded,
296  DWORD *pcbEncoded)
297 {
298     BOOL ret;
299     DWORD i, dataLen = 0;
300
301     TRACE("%p, %d, %p, %d\n", items, cItem, pbEncoded, *pcbEncoded);
302     for (i = 0, ret = TRUE; ret && i < cItem; i++)
303     {
304         ret = items[i].encodeFunc(dwCertEncodingType, NULL,
305          items[i].pvStructInfo, NULL, &items[i].size);
306         /* Some functions propagate their errors through the size */
307         if (!ret)
308             *pcbEncoded = items[i].size;
309         dataLen += items[i].size;
310     }
311     if (ret)
312     {
313         DWORD lenBytes, bytesNeeded;
314
315         CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
316         bytesNeeded = 1 + lenBytes + dataLen;
317         if (!pbEncoded)
318             *pcbEncoded = bytesNeeded;
319         else if (*pcbEncoded < bytesNeeded)
320         {
321             *pcbEncoded = bytesNeeded;
322             SetLastError(ERROR_MORE_DATA);
323             ret = FALSE;
324         }
325         else
326         {
327             *pcbEncoded = bytesNeeded;
328             *pbEncoded++ = ASN_SEQUENCE;
329             CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
330             pbEncoded += lenBytes;
331             for (i = 0; ret && i < cItem; i++)
332             {
333                 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
334                  items[i].pvStructInfo, pbEncoded, &items[i].size);
335                 /* Some functions propagate their errors through the size */
336                 if (!ret)
337                     *pcbEncoded = items[i].size;
338                 pbEncoded += items[i].size;
339             }
340         }
341     }
342     TRACE("returning %d\n", ret);
343     return ret;
344 }
345
346 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
347  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
348  DWORD *pcbEncoded)
349 {
350     BOOL ret = FALSE;
351
352     __TRY
353     {
354         const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
355         DWORD bytesNeeded, lenBytes, dataBytes;
356         BYTE unusedBits;
357
358         /* yep, MS allows cUnusedBits to be >= 8 */
359         if (!blob->cUnusedBits)
360         {
361             dataBytes = blob->cbData;
362             unusedBits = 0;
363         }
364         else if (blob->cbData * 8 > blob->cUnusedBits)
365         {
366             dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
367             unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
368              blob->cUnusedBits;
369         }
370         else
371         {
372             dataBytes = 0;
373             unusedBits = 0;
374         }
375         CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
376         bytesNeeded = 1 + lenBytes + dataBytes + 1;
377         if (!pbEncoded)
378         {
379             *pcbEncoded = bytesNeeded;
380             ret = TRUE;
381         }
382         else if (*pcbEncoded < bytesNeeded)
383         {
384             *pcbEncoded = bytesNeeded;
385             SetLastError(ERROR_MORE_DATA);
386         }
387         else
388         {
389             ret = TRUE;
390             *pcbEncoded = bytesNeeded;
391             *pbEncoded++ = ASN_BITSTRING;
392             CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
393             pbEncoded += lenBytes;
394             *pbEncoded++ = unusedBits;
395             if (dataBytes)
396             {
397                 BYTE mask = 0xff << unusedBits;
398
399                 if (dataBytes > 1)
400                 {
401                     memcpy(pbEncoded, blob->pbData, dataBytes - 1);
402                     pbEncoded += dataBytes - 1;
403                 }
404                 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
405             }
406         }
407     }
408     __EXCEPT_PAGE_FAULT
409     {
410         SetLastError(STATUS_ACCESS_VIOLATION);
411     }
412     __ENDTRY
413     return ret;
414 }
415
416 struct AsnConstructedItem
417 {
418     BYTE                  tag;
419     const void           *pvStructInfo;
420     CryptEncodeObjectFunc encodeFunc;
421 };
422
423 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
424  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
425  DWORD *pcbEncoded)
426 {
427     BOOL ret;
428     const struct AsnConstructedItem *item =
429      (const struct AsnConstructedItem *)pvStructInfo;
430     DWORD len;
431
432     if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
433      item->pvStructInfo, NULL, &len)))
434     {
435         DWORD dataLen, bytesNeeded;
436
437         CRYPT_EncodeLen(len, NULL, &dataLen);
438         bytesNeeded = 1 + dataLen + len;
439         if (!pbEncoded)
440             *pcbEncoded = bytesNeeded;
441         else if (*pcbEncoded < bytesNeeded)
442         {
443             *pcbEncoded = bytesNeeded;
444             SetLastError(ERROR_MORE_DATA);
445             ret = FALSE;
446         }
447         else
448         {
449             *pcbEncoded = bytesNeeded;
450             *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
451             CRYPT_EncodeLen(len, pbEncoded, &dataLen);
452             pbEncoded += dataLen;
453             ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
454              item->pvStructInfo, pbEncoded, &len);
455             if (!ret)
456             {
457                 /* Some functions propagate their errors through the size */
458                 *pcbEncoded = len;
459             }
460         }
461     }
462     else
463     {
464         /* Some functions propagate their errors through the size */
465         *pcbEncoded = len;
466     }
467     return ret;
468 }
469
470
471 BOOL WINAPI WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType,
472  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
473  DWORD *pcbEncoded)
474 {
475     const SPC_PE_IMAGE_DATA *imageData =
476      (const SPC_PE_IMAGE_DATA *)pvStructInfo;
477     BOOL ret = FALSE;
478
479     TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
480      debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
481      pcbEncoded);
482
483     __TRY
484     {
485         struct AsnEncodeSequenceItem items[2] = {
486          { 0 }
487         };
488         struct AsnConstructedItem constructed = { 0, imageData->pFile,
489          WVTAsn1SpcLinkEncode };
490         DWORD cItem = 0;
491
492         if (imageData->Flags.cbData)
493         {
494             items[cItem].pvStructInfo = &imageData->Flags;
495             items[cItem].encodeFunc = CRYPT_AsnEncodeBits;
496             cItem++;
497         }
498         if (imageData->pFile)
499         {
500             items[cItem].pvStructInfo = &constructed;
501             items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
502             cItem++;
503         }
504
505         ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
506          pbEncoded, pcbEncoded);
507     }
508     __EXCEPT_PAGE_FAULT
509     {
510         SetLastError(STATUS_ACCESS_VIOLATION);
511     }
512     __ENDTRY
513     TRACE("returning %d\n", ret);
514     return ret;
515 }
516
517 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
518  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
519  DWORD *pcbEncoded)
520 {
521     LPCSTR pszObjId = (LPCSTR)pvStructInfo;
522     DWORD bytesNeeded = 0, lenBytes;
523     BOOL ret = TRUE;
524     int firstPos = 0;
525     BYTE firstByte = 0;
526
527     TRACE("%s\n", debugstr_a(pszObjId));
528
529     if (pszObjId)
530     {
531         const char *ptr;
532         int val1, val2;
533
534         if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
535         {
536             SetLastError(CRYPT_E_ASN1_ERROR);
537             return FALSE;
538         }
539         bytesNeeded++;
540         firstByte = val1 * 40 + val2;
541         ptr = pszObjId + firstPos;
542         while (ret && *ptr)
543         {
544             int pos;
545
546             /* note I assume each component is at most 32-bits long in base 2 */
547             if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
548             {
549                 if (val1 >= 0x10000000)
550                     bytesNeeded += 5;
551                 else if (val1 >= 0x200000)
552                     bytesNeeded += 4;
553                 else if (val1 >= 0x4000)
554                     bytesNeeded += 3;
555                 else if (val1 >= 0x80)
556                     bytesNeeded += 2;
557                 else
558                     bytesNeeded += 1;
559                 ptr += pos;
560                 if (*ptr == '.')
561                     ptr++;
562             }
563             else
564             {
565                 SetLastError(CRYPT_E_ASN1_ERROR);
566                 return FALSE;
567             }
568         }
569         CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
570     }
571     else
572         lenBytes = 1;
573     bytesNeeded += 1 + lenBytes;
574     if (pbEncoded)
575     {
576         if (*pcbEncoded < bytesNeeded)
577         {
578             SetLastError(ERROR_MORE_DATA);
579             ret = FALSE;
580         }
581         else
582         {
583             *pbEncoded++ = ASN_OBJECTIDENTIFIER;
584             CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
585             pbEncoded += lenBytes;
586             if (pszObjId)
587             {
588                 const char *ptr;
589                 int val, pos;
590
591                 *pbEncoded++ = firstByte;
592                 ptr = pszObjId + firstPos;
593                 while (ret && *ptr)
594                 {
595                     sscanf(ptr, "%d%n", &val, &pos);
596                     {
597                         unsigned char outBytes[5];
598                         int numBytes, i;
599
600                         if (val >= 0x10000000)
601                             numBytes = 5;
602                         else if (val >= 0x200000)
603                             numBytes = 4;
604                         else if (val >= 0x4000)
605                             numBytes = 3;
606                         else if (val >= 0x80)
607                             numBytes = 2;
608                         else
609                             numBytes = 1;
610                         for (i = numBytes; i > 0; i--)
611                         {
612                             outBytes[i - 1] = val & 0x7f;
613                             val >>= 7;
614                         }
615                         for (i = 0; i < numBytes - 1; i++)
616                             *pbEncoded++ = outBytes[i] | 0x80;
617                         *pbEncoded++ = outBytes[i];
618                         ptr += pos;
619                         if (*ptr == '.')
620                             ptr++;
621                     }
622                 }
623             }
624         }
625     }
626     *pcbEncoded = bytesNeeded;
627     return ret;
628 }
629
630 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
631  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
632  DWORD *pcbEncoded)
633 {
634     const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
635     BOOL ret = TRUE;
636
637     if (!pbEncoded)
638         *pcbEncoded = blob->cbData;
639     else if (*pcbEncoded < blob->cbData)
640     {
641         *pcbEncoded = blob->cbData;
642         SetLastError(ERROR_MORE_DATA);
643         ret = FALSE;
644     }
645     else
646     {
647         if (blob->cbData)
648             memcpy(pbEncoded, blob->pbData, blob->cbData);
649         *pcbEncoded = blob->cbData;
650     }
651     return ret;
652 }
653
654 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
655  DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
656  BYTE *pbEncoded, DWORD *pcbEncoded)
657 {
658     const CRYPT_ALGORITHM_IDENTIFIER *algo =
659      (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
660     static const BYTE asn1Null[] = { ASN_NULL, 0 };
661     static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
662      (LPBYTE)asn1Null };
663     BOOL ret;
664     struct AsnEncodeSequenceItem items[2] = {
665      { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
666      { NULL,           CRYPT_CopyEncodedBlob, 0 },
667     };
668
669     if (algo->Parameters.cbData)
670         items[1].pvStructInfo = &algo->Parameters;
671     else
672         items[1].pvStructInfo = &nullBlob;
673     ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
674      sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
675     return ret;
676 }
677
678 static BOOL WINAPI CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType,
679  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
680  DWORD *pcbEncoded)
681 {
682     const CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue =
683      (const CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
684     struct AsnEncodeSequenceItem items[] = {
685      { &typeValue->pszObjId, CRYPT_AsnEncodeOid, 0 },
686      { &typeValue->Value,    CRYPT_CopyEncodedBlob, 0 },
687     };
688
689     return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
690      items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
691 }
692
693 struct SPCDigest
694 {
695     CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm;
696     CRYPT_HASH_BLOB            Digest;
697 };
698
699 static BOOL WINAPI CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType,
700  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
701  DWORD *pcbEncoded)
702 {
703     const struct SPCDigest *digest = (const struct SPCDigest *)pvStructInfo;
704     struct AsnEncodeSequenceItem items[] = {
705      { &digest->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
706      { &digest->Digest,          CRYPT_CopyEncodedBlob, 0 },
707     };
708
709     return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
710      items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
711 }
712
713 BOOL WINAPI WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType,
714  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
715  DWORD *pcbEncoded)
716 {
717     BOOL ret = FALSE;
718
719     TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
720      debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
721
722     __TRY
723     {
724         const SPC_INDIRECT_DATA_CONTENT *data =
725          (const SPC_INDIRECT_DATA_CONTENT *)pvStructInfo;
726         struct AsnEncodeSequenceItem items[] = {
727          { &data->Data,            CRYPT_AsnEncodeAttributeTypeValue, 0 },
728          { &data->DigestAlgorithm, CRYPT_AsnEncodeSPCDigest, 0 },
729         };
730
731         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
732          items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
733     }
734     __EXCEPT_PAGE_FAULT
735     {
736         SetLastError(STATUS_ACCESS_VIOLATION);
737     }
738     __ENDTRY
739     return ret;
740 }
741
742 static BOOL WINAPI CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType,
743  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
744  DWORD *pcbEncoded)
745 {
746     BOOL ret = TRUE;
747     LPCWSTR str = (LPCWSTR)pvStructInfo;
748     DWORD bytesNeeded, lenBytes, strLen;
749
750     if (str)
751         strLen = lstrlenW(str);
752     else
753         strLen = 0;
754     CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
755     bytesNeeded = 1 + lenBytes + strLen * 2;
756     if (!pbEncoded)
757         *pcbEncoded = bytesNeeded;
758     else if (*pcbEncoded < bytesNeeded)
759     {
760         *pcbEncoded = bytesNeeded;
761         SetLastError(ERROR_MORE_DATA);
762         ret = FALSE;
763     }
764     else
765     {
766         DWORD i;
767
768         *pcbEncoded = bytesNeeded;
769         *pbEncoded++ = ASN_BMPSTRING;
770         CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
771         pbEncoded += lenBytes;
772         for (i = 0; i < strLen; i++)
773         {
774             *pbEncoded++ = (str[i] & 0xff00) >> 8;
775             *pbEncoded++ = str[i] & 0x00ff;
776         }
777     }
778     return ret;
779 }
780
781 static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
782  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
783  DWORD *pcbEncoded)
784 {
785     BOOL ret;
786
787     __TRY
788     {
789         DWORD significantBytes, lenBytes, bytesNeeded;
790         BYTE padByte = 0;
791         BOOL pad = FALSE;
792         const CRYPT_INTEGER_BLOB *blob =
793          (const CRYPT_INTEGER_BLOB *)pvStructInfo;
794
795         significantBytes = blob->cbData;
796         if (significantBytes)
797         {
798             if (blob->pbData[significantBytes - 1] & 0x80)
799             {
800                 /* negative, lop off leading (little-endian) 0xffs */
801                 for (; significantBytes > 0 &&
802                  blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
803                     ;
804                 if (blob->pbData[significantBytes - 1] < 0x80)
805                 {
806                     padByte = 0xff;
807                     pad = TRUE;
808                 }
809             }
810             else
811             {
812                 /* positive, lop off leading (little-endian) zeroes */
813                 for (; significantBytes > 0 &&
814                  !blob->pbData[significantBytes - 1]; significantBytes--)
815                     ;
816                 if (significantBytes == 0)
817                     significantBytes = 1;
818                 if (blob->pbData[significantBytes - 1] > 0x7f)
819                 {
820                     padByte = 0;
821                     pad = TRUE;
822                 }
823             }
824         }
825         if (pad)
826             CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
827         else
828             CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
829         bytesNeeded = 1 + lenBytes + significantBytes;
830         if (pad)
831             bytesNeeded++;
832         if (!pbEncoded)
833         {
834             *pcbEncoded = bytesNeeded;
835             ret = TRUE;
836         }
837         else if (*pcbEncoded < bytesNeeded)
838         {
839             *pcbEncoded = bytesNeeded;
840             SetLastError(ERROR_MORE_DATA);
841             ret = FALSE;
842         }
843         else
844         {
845             *pcbEncoded = bytesNeeded;
846             *pbEncoded++ = ASN_INTEGER;
847             if (pad)
848             {
849                 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
850                 pbEncoded += lenBytes;
851                 *pbEncoded++ = padByte;
852             }
853             else
854             {
855                 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
856                 pbEncoded += lenBytes;
857             }
858             for (; significantBytes > 0; significantBytes--)
859                 *(pbEncoded++) = blob->pbData[significantBytes - 1];
860             ret = TRUE;
861         }
862     }
863     __EXCEPT_PAGE_FAULT
864     {
865         SetLastError(STATUS_ACCESS_VIOLATION);
866         ret = FALSE;
867     }
868     __ENDTRY
869     return ret;
870 }
871
872 BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
873  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
874  DWORD *pcbEncoded)
875 {
876     CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
877
878     return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
879      &blob, pbEncoded, pcbEncoded);
880 }
881
882 BOOL WINAPI WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType,
883  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
884  DWORD *pcbEncoded)
885 {
886     BOOL ret = FALSE;
887
888     TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
889      debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
890
891     __TRY
892     {
893         const CAT_MEMBERINFO *info = (const CAT_MEMBERINFO *)pvStructInfo;
894         struct AsnEncodeSequenceItem items[] = {
895          { info->pwszSubjGuid, CRYPT_AsnEncodeBMPString, 0 },
896          { &info->dwCertVersion, CRYPT_AsnEncodeInt, 0 },
897         };
898
899         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
900          items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
901     }
902     __EXCEPT_PAGE_FAULT
903     {
904         SetLastError(STATUS_ACCESS_VIOLATION);
905     }
906     __ENDTRY
907     return ret;
908 }
909
910 BOOL WINAPI WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType,
911  LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
912  DWORD *pcbEncoded)
913 {
914     BOOL ret = FALSE;
915
916     TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
917      debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
918
919     __TRY
920     {
921         const CAT_NAMEVALUE *value = (const CAT_NAMEVALUE *)pvStructInfo;
922         struct AsnEncodeSequenceItem items[] = {
923          { value->pwszTag,   CRYPT_AsnEncodeBMPString, 0 },
924          { &value->fdwFlags, CRYPT_AsnEncodeInt, 0 },
925          { &value->Value,    CRYPT_AsnEncodeOctets, 0 },
926         };
927
928         ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
929          items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
930     }
931     __EXCEPT_PAGE_FAULT
932     {
933         SetLastError(STATUS_ACCESS_VIOLATION);
934     }
935     __ENDTRY
936     return ret;
937 }
938
939 /* Gets the number of length bytes from the given (leading) length byte */
940 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
941
942 /* Helper function to get the encoded length of the data starting at pbEncoded,
943  * where pbEncoded[0] is the tag.  If the data are too short to contain a
944  * length or if the length is too large for cbEncoded, sets an appropriate
945  * error code and returns FALSE.
946  */
947 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
948 {
949     BOOL ret;
950
951     if (cbEncoded <= 1)
952     {
953         SetLastError(CRYPT_E_ASN1_CORRUPT);
954         ret = FALSE;
955     }
956     else if (pbEncoded[1] <= 0x7f)
957     {
958         if (pbEncoded[1] + 1 > cbEncoded)
959         {
960             SetLastError(CRYPT_E_ASN1_EOD);
961             ret = FALSE;
962         }
963         else
964         {
965             *len = pbEncoded[1];
966             ret = TRUE;
967         }
968     }
969     else if (pbEncoded[1] == 0x80)
970     {
971         FIXME("unimplemented for indefinite-length encoding\n");
972         SetLastError(CRYPT_E_ASN1_CORRUPT);
973         ret = FALSE;
974     }
975     else
976     {
977         BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
978
979         if (lenLen > sizeof(DWORD) + 1)
980         {
981             SetLastError(CRYPT_E_ASN1_LARGE);
982             ret = FALSE;
983         }
984         else if (lenLen + 2 > cbEncoded)
985         {
986             SetLastError(CRYPT_E_ASN1_CORRUPT);
987             ret = FALSE;
988         }
989         else
990         {
991             DWORD out = 0;
992
993             pbEncoded += 2;
994             while (--lenLen)
995             {
996                 out <<= 8;
997                 out |= *pbEncoded++;
998             }
999             if (out + lenLen + 1 > cbEncoded)
1000             {
1001                 SetLastError(CRYPT_E_ASN1_EOD);
1002                 ret = FALSE;
1003             }
1004             else
1005             {
1006                 *len = out;
1007                 ret = TRUE;
1008             }
1009         }
1010     }
1011     return ret;
1012 }
1013
1014 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
1015  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1016  void *pvStructInfo, DWORD *pcbStructInfo)
1017 {
1018     BOOL ret;
1019     DWORD bytesNeeded, dataLen;
1020
1021     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1022      pvStructInfo, *pcbStructInfo);
1023
1024     if (!cbEncoded)
1025     {
1026         SetLastError(CRYPT_E_ASN1_CORRUPT);
1027         ret = FALSE;
1028     }
1029     else if (pbEncoded[0] != ASN_OCTETSTRING)
1030     {
1031         SetLastError(CRYPT_E_ASN1_BADTAG);
1032         ret = FALSE;
1033     }
1034     else if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1035     {
1036         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1037             bytesNeeded = sizeof(CRYPT_DATA_BLOB);
1038         else
1039             bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
1040         if (!pvStructInfo)
1041             *pcbStructInfo = bytesNeeded;
1042         else if (*pcbStructInfo < bytesNeeded)
1043         {
1044             SetLastError(ERROR_MORE_DATA);
1045             *pcbStructInfo = bytesNeeded;
1046             ret = FALSE;
1047         }
1048         else
1049         {
1050             CRYPT_DATA_BLOB *blob;
1051             BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1052
1053             blob = (CRYPT_DATA_BLOB *)pvStructInfo;
1054             blob->cbData = dataLen;
1055             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1056                 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
1057             else
1058             {
1059                 assert(blob->pbData);
1060                 if (blob->cbData)
1061                     memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
1062                      blob->cbData);
1063             }
1064         }
1065     }
1066     return ret;
1067 }
1068
1069 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType,
1070  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1071  void *pvStructInfo, DWORD *pcbStructInfo)
1072 {
1073     BOOL ret = FALSE;
1074     DWORD bytesNeeded = sizeof(SPC_LINK), dataLen;
1075
1076     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1077      pvStructInfo, *pcbStructInfo);
1078
1079     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1080     {
1081         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1082         DWORD realDataLen;
1083
1084         switch (pbEncoded[0])
1085         {
1086         case ASN_CONTEXT:
1087             bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1088             if (!pvStructInfo)
1089                 *pcbStructInfo = bytesNeeded;
1090             else if (*pcbStructInfo < bytesNeeded)
1091             {
1092                 *pcbStructInfo = bytesNeeded;
1093                 SetLastError(ERROR_MORE_DATA);
1094                 ret = FALSE;
1095             }
1096             else
1097             {
1098                 PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1099                 DWORD i;
1100
1101                 link->dwLinkChoice = SPC_URL_LINK_CHOICE;
1102                 for (i = 0; i < dataLen; i++)
1103                     link->u.pwszUrl[i] =
1104                      *(pbEncoded + 1 + lenBytes + i);
1105                 link->u.pwszUrl[i] = '\0';
1106                 TRACE("returning url %s\n", debugstr_w(link->u.pwszUrl));
1107             }
1108             break;
1109         case ASN_CONSTRUCTOR | ASN_CONTEXT | 1:
1110         {
1111             CRYPT_DATA_BLOB classId;
1112             DWORD size = sizeof(classId);
1113
1114             if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
1115              pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
1116              CRYPT_DECODE_NOCOPY_FLAG, &classId, &size)))
1117             {
1118                 if (classId.cbData != sizeof(SPC_UUID))
1119                 {
1120                     SetLastError(CRYPT_E_BAD_ENCODE);
1121                     ret = FALSE;
1122                 }
1123                 else
1124                 {
1125                     CRYPT_DATA_BLOB data;
1126
1127                     /* The tag length for the classId must be 1 since the
1128                      * length is correct.
1129                      */
1130                     size = sizeof(data);
1131                     if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
1132                      pbEncoded + 3 + lenBytes + classId.cbData,
1133                      cbEncoded - 3 - lenBytes - classId.cbData,
1134                      CRYPT_DECODE_NOCOPY_FLAG, &data, &size)))
1135                     {
1136                         bytesNeeded += data.cbData;
1137                         if (!pvStructInfo)
1138                             *pcbStructInfo = bytesNeeded;
1139                         else if (*pcbStructInfo < bytesNeeded)
1140                         {
1141                             *pcbStructInfo = bytesNeeded;
1142                             SetLastError(ERROR_MORE_DATA);
1143                             ret = FALSE;
1144                         }
1145                         else
1146                         {
1147                             PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1148
1149                             link->dwLinkChoice = SPC_MONIKER_LINK_CHOICE;
1150                             /* pwszFile pointer was set by caller, copy it
1151                              * before overwriting it
1152                              */
1153                             link->u.Moniker.SerializedData.pbData =
1154                              (BYTE *)link->u.pwszFile;
1155                             memcpy(link->u.Moniker.ClassId, classId.pbData,
1156                              classId.cbData);
1157                             memcpy(link->u.Moniker.SerializedData.pbData,
1158                              data.pbData, data.cbData);
1159                             link->u.Moniker.SerializedData.cbData = data.cbData;
1160                         }
1161                     }
1162                 }
1163             }
1164             break;
1165         }
1166         case ASN_CONSTRUCTOR | ASN_CONTEXT | 2:
1167             if (dataLen && pbEncoded[1 + lenBytes] != ASN_CONTEXT)
1168                 SetLastError(CRYPT_E_ASN1_BADTAG);
1169             else if ((ret = CRYPT_GetLen(pbEncoded + 1 + lenBytes, dataLen,
1170              &realDataLen)))
1171             {
1172                 BYTE realLenBytes = GET_LEN_BYTES(pbEncoded[2 + lenBytes]);
1173
1174                 bytesNeeded += realDataLen + sizeof(WCHAR);
1175                 if (!pvStructInfo)
1176                     *pcbStructInfo = bytesNeeded;
1177                 else if (*pcbStructInfo < bytesNeeded)
1178                 {
1179                     *pcbStructInfo = bytesNeeded;
1180                     SetLastError(ERROR_MORE_DATA);
1181                     ret = FALSE;
1182                 }
1183                 else
1184                 {
1185                     PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1186                     DWORD i;
1187                     const BYTE *ptr = pbEncoded + 2 + lenBytes + realLenBytes;
1188
1189                     link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1190                     for (i = 0; i < dataLen / sizeof(WCHAR); i++)
1191                         link->u.pwszFile[i] =
1192                          hton16(*(WORD *)(ptr + i * sizeof(WCHAR)));
1193                     link->u.pwszFile[realDataLen / sizeof(WCHAR)] = '\0';
1194                     TRACE("returning file %s\n", debugstr_w(link->u.pwszFile));
1195                 }
1196             }
1197             else
1198             {
1199                 bytesNeeded += sizeof(WCHAR);
1200                 if (!pvStructInfo)
1201                     *pcbStructInfo = bytesNeeded;
1202                 else if (*pcbStructInfo < bytesNeeded)
1203                 {
1204                     *pcbStructInfo = bytesNeeded;
1205                     SetLastError(ERROR_MORE_DATA);
1206                     ret = FALSE;
1207                 }
1208                 else
1209                 {
1210                     PSPC_LINK link = (PSPC_LINK)pvStructInfo;
1211
1212                     link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1213                     link->u.pwszFile[0] = '\0';
1214                     ret = TRUE;
1215                 }
1216             }
1217             break;
1218         default:
1219             SetLastError(CRYPT_E_ASN1_BADTAG);
1220         }
1221     }
1222     TRACE("returning %d\n", ret);
1223     return ret;
1224 }
1225
1226 BOOL WINAPI WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType,
1227  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1228  void *pvStructInfo, DWORD *pcbStructInfo)
1229 {
1230     BOOL ret = FALSE;
1231
1232     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1233      pvStructInfo, *pcbStructInfo);
1234
1235     __TRY
1236     {
1237         DWORD bytesNeeded;
1238
1239         ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1240          lpszStructType, pbEncoded, cbEncoded, dwFlags, NULL, &bytesNeeded);
1241         if (ret)
1242         {
1243             if (!pvStructInfo)
1244                 *pcbStructInfo = bytesNeeded;
1245             else if (*pcbStructInfo < bytesNeeded)
1246             {
1247                 *pcbStructInfo = bytesNeeded;
1248                 SetLastError(ERROR_MORE_DATA);
1249                 ret = FALSE;
1250             }
1251             else
1252             {
1253                 SPC_LINK *link = (SPC_LINK *)pvStructInfo;
1254
1255                 link->u.pwszFile =
1256                  (LPWSTR)((BYTE *)pvStructInfo + sizeof(SPC_LINK));
1257                 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1258                  lpszStructType, pbEncoded, cbEncoded, dwFlags, pvStructInfo,
1259                  pcbStructInfo);
1260             }
1261         }
1262     }
1263     __EXCEPT_PAGE_FAULT
1264     {
1265         SetLastError(STATUS_ACCESS_VIOLATION);
1266     }
1267     __ENDTRY
1268     TRACE("returning %d\n", ret);
1269     return ret;
1270 }
1271
1272 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
1273  DWORD, DWORD, void *, DWORD *);
1274
1275 /* tag:
1276  *     The expected tag of the item.  If tag is 0, decodeFunc is called
1277  *     regardless of the tag value seen.
1278  * offset:
1279  *     A sequence is decoded into a struct.  The offset member is the
1280  *     offset of this item within that struct.
1281  * decodeFunc:
1282  *     The decoder function to use.  If this is NULL, then the member isn't
1283  *     decoded, but minSize space is reserved for it.
1284  * minSize:
1285  *     The minimum amount of space occupied after decoding.  You must set this.
1286  * optional:
1287  *     If true, and the tag doesn't match the expected tag for this item,
1288  *     or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1289  *     filled with 0 for this member.
1290  * hasPointer, pointerOffset:
1291  *     If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1292  *     the offset within the struct of the data pointer (or to the
1293  *     first data pointer, if more than one exist).
1294  * size:
1295  *     Used by CRYPT_AsnDecodeSequence, not for your use.
1296  */
1297 struct AsnDecodeSequenceItem
1298 {
1299     BYTE                  tag;
1300     DWORD                 offset;
1301     CryptDecodeObjectFunc decodeFunc;
1302     DWORD                 minSize;
1303     BOOL                  optional;
1304     BOOL                  hasPointer;
1305     DWORD                 pointerOffset;
1306     DWORD                 size;
1307 };
1308
1309 /* Decodes the items in a sequence, where the items are described in items,
1310  * the encoded data are in pbEncoded with length cbEncoded.  Decodes into
1311  * pvStructInfo.  nextData is a pointer to the memory location at which the
1312  * first decoded item with a dynamic pointer should point.
1313  * Upon decoding, *cbDecoded is the total number of bytes decoded.
1314  */
1315 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
1316  struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1317  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
1318  DWORD *cbDecoded)
1319 {
1320     BOOL ret;
1321     DWORD i, decoded = 0;
1322     const BYTE *ptr = pbEncoded;
1323
1324     TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
1325      cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
1326
1327     for (i = 0, ret = TRUE; ret && i < cItem; i++)
1328     {
1329         if (cbEncoded - (ptr - pbEncoded) != 0)
1330         {
1331             DWORD nextItemLen;
1332
1333             if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
1334              &nextItemLen)))
1335             {
1336                 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
1337
1338                 if (ptr[0] == items[i].tag || !items[i].tag)
1339                 {
1340                     if (nextData && pvStructInfo && items[i].hasPointer)
1341                     {
1342                         TRACE("Setting next pointer to %p\n",
1343                          nextData);
1344                         *(BYTE **)((BYTE *)pvStructInfo +
1345                          items[i].pointerOffset) = nextData;
1346                     }
1347                     if (items[i].decodeFunc)
1348                     {
1349                         if (pvStructInfo)
1350                             TRACE("decoding item %d\n", i);
1351                         else
1352                             TRACE("sizing item %d\n", i);
1353                         ret = items[i].decodeFunc(dwCertEncodingType,
1354                          NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
1355                          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
1356                          pvStructInfo ?  (BYTE *)pvStructInfo + items[i].offset
1357                          : NULL, &items[i].size);
1358                         if (ret)
1359                         {
1360                             /* Account for alignment padding */
1361                             if (items[i].size % sizeof(DWORD))
1362                                 items[i].size += sizeof(DWORD) -
1363                                  items[i].size % sizeof(DWORD);
1364                             TRACE("item %d size: %d\n", i, items[i].size);
1365                             if (nextData && items[i].hasPointer &&
1366                              items[i].size > items[i].minSize)
1367                                 nextData += items[i].size - items[i].minSize;
1368                             ptr += 1 + nextItemLenBytes + nextItemLen;
1369                             decoded += 1 + nextItemLenBytes + nextItemLen;
1370                             TRACE("item %d: decoded %d bytes\n", i,
1371                              1 + nextItemLenBytes + nextItemLen);
1372                         }
1373                         else if (items[i].optional &&
1374                          GetLastError() == CRYPT_E_ASN1_BADTAG)
1375                         {
1376                             TRACE("skipping optional item %d\n", i);
1377                             items[i].size = items[i].minSize;
1378                             SetLastError(NOERROR);
1379                             ret = TRUE;
1380                         }
1381                         else
1382                             TRACE("item %d failed: %08x\n", i,
1383                              GetLastError());
1384                     }
1385                     else
1386                     {
1387                         TRACE("item %d: decoded %d bytes\n", i,
1388                          1 + nextItemLenBytes + nextItemLen);
1389                         ptr += 1 + nextItemLenBytes + nextItemLen;
1390                         decoded += 1 + nextItemLenBytes + nextItemLen;
1391                         items[i].size = items[i].minSize;
1392                     }
1393                 }
1394                 else if (items[i].optional)
1395                 {
1396                     TRACE("skipping optional item %d\n", i);
1397                     items[i].size = items[i].minSize;
1398                 }
1399                 else
1400                 {
1401                     TRACE("item %d: tag %02x doesn't match expected %02x\n",
1402                      i, ptr[0], items[i].tag);
1403                     SetLastError(CRYPT_E_ASN1_BADTAG);
1404                     ret = FALSE;
1405                 }
1406             }
1407         }
1408         else if (items[i].optional)
1409         {
1410             TRACE("missing optional item %d, skipping\n", i);
1411             items[i].size = items[i].minSize;
1412         }
1413         else
1414         {
1415             TRACE("not enough bytes for item %d, failing\n", i);
1416             SetLastError(CRYPT_E_ASN1_CORRUPT);
1417             ret = FALSE;
1418         }
1419     }
1420     if (ret)
1421         *cbDecoded = decoded;
1422     TRACE("returning %d\n", ret);
1423     return ret;
1424 }
1425
1426 /* This decodes an arbitrary sequence into a contiguous block of memory
1427  * (basically, a struct.)  Each element being decoded is described by a struct
1428  * AsnDecodeSequenceItem, see above.
1429  * startingPointer is an optional pointer to the first place where dynamic
1430  * data will be stored.  If you know the starting offset, you may pass it
1431  * here.  Otherwise, pass NULL, and one will be inferred from the items.
1432  */
1433 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
1434  struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1435  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1436  void *startingPointer)
1437 {
1438     BOOL ret;
1439
1440     TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items, cItem, pbEncoded,
1441      cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, startingPointer);
1442
1443     if (pbEncoded[0] == ASN_SEQUENCE)
1444     {
1445         DWORD dataLen;
1446
1447         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1448         {
1449             DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
1450             const BYTE *ptr = pbEncoded + 1 + lenBytes;
1451
1452             cbEncoded -= 1 + lenBytes;
1453             if (cbEncoded < dataLen)
1454             {
1455                 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
1456                  cbEncoded);
1457                 SetLastError(CRYPT_E_ASN1_CORRUPT);
1458                 ret = FALSE;
1459             }
1460             else
1461                 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
1462                  cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
1463             if (ret && cbDecoded != dataLen)
1464             {
1465                 TRACE("expected %d decoded, got %d, failing\n", dataLen,
1466                  cbDecoded);
1467                 SetLastError(CRYPT_E_ASN1_CORRUPT);
1468                 ret = FALSE;
1469             }
1470             if (ret)
1471             {
1472                 DWORD i, bytesNeeded = 0, structSize = 0;
1473
1474                 for (i = 0; i < cItem; i++)
1475                 {
1476                     bytesNeeded += items[i].size;
1477                     structSize += items[i].minSize;
1478                 }
1479                 if (!pvStructInfo)
1480                     *pcbStructInfo = bytesNeeded;
1481                 else if (*pcbStructInfo < bytesNeeded)
1482                 {
1483                     SetLastError(ERROR_MORE_DATA);
1484                     *pcbStructInfo = bytesNeeded;
1485                     ret = FALSE;
1486                 }
1487                 else
1488                 {
1489                     BYTE *nextData;
1490
1491                     *pcbStructInfo = bytesNeeded;
1492                     if (startingPointer)
1493                         nextData = (BYTE *)startingPointer;
1494                     else
1495                         nextData = (BYTE *)pvStructInfo + structSize;
1496                     memset(pvStructInfo, 0, structSize);
1497                     ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
1498                      ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
1499                      &cbDecoded);
1500                 }
1501             }
1502         }
1503     }
1504     else
1505     {
1506         SetLastError(CRYPT_E_ASN1_BADTAG);
1507         ret = FALSE;
1508     }
1509     TRACE("returning %d (%08x)\n", ret, GetLastError());
1510     return ret;
1511 }
1512
1513 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
1514  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1515  void *pvStructInfo, DWORD *pcbStructInfo)
1516 {
1517     BOOL ret;
1518
1519     TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
1520      pvStructInfo, *pcbStructInfo);
1521
1522     if (pbEncoded[0] == ASN_BITSTRING)
1523     {
1524         DWORD bytesNeeded, dataLen;
1525
1526         if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1527         {
1528             if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1529                 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
1530             else
1531                 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
1532             if (!pvStructInfo)
1533                 *pcbStructInfo = bytesNeeded;
1534             else if (*pcbStructInfo < bytesNeeded)
1535             {
1536                 *pcbStructInfo = bytesNeeded;
1537                 SetLastError(ERROR_MORE_DATA);
1538                 ret = FALSE;
1539             }
1540             else
1541             {
1542                 CRYPT_BIT_BLOB *blob;
1543
1544                 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
1545                 blob->cbData = dataLen - 1;
1546                 blob->cUnusedBits = *(pbEncoded + 1 +
1547                  GET_LEN_BYTES(pbEncoded[1]));
1548                 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1549                 {
1550                     blob->pbData = (BYTE *)pbEncoded + 2 +
1551                      GET_LEN_BYTES(pbEncoded[1]);
1552                 }
1553                 else
1554                 {
1555                     assert(blob->pbData);
1556                     if (blob->cbData)
1557                     {
1558                         BYTE mask = 0xff << blob->cUnusedBits;
1559
1560                         memcpy(blob->pbData, pbEncoded + 2 +
1561                          GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
1562                         blob->pbData[blob->cbData - 1] &= mask;
1563                     }
1564                 }
1565             }
1566         }
1567     }
1568     else
1569     {
1570         SetLastError(CRYPT_E_ASN1_BADTAG);
1571         ret = FALSE;
1572     }
1573     TRACE("returning %d (%08x)\n", ret, GetLastError());
1574     return ret;
1575 }
1576
1577 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType,
1578  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1579  void *pvStructInfo, DWORD *pcbStructInfo)
1580 {
1581     BOOL ret = FALSE;
1582     DWORD dataLen;
1583
1584     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1585     {
1586         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1587         DWORD size;
1588         SPC_LINK **pLink = (SPC_LINK **)pvStructInfo;
1589
1590         ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType, lpszStructType,
1591          pbEncoded + 1 + lenBytes, dataLen, dwFlags, NULL, &size);
1592         if (ret)
1593         {
1594             if (!pvStructInfo)
1595                 *pcbStructInfo = size + sizeof(PSPC_LINK);
1596             else if (*pcbStructInfo < size + sizeof(PSPC_LINK))
1597             {
1598                 *pcbStructInfo = size + sizeof(PSPC_LINK);
1599                 SetLastError(ERROR_MORE_DATA);
1600                 ret = FALSE;
1601             }
1602             else
1603             {
1604                 *pcbStructInfo = size + sizeof(PSPC_LINK);
1605                 /* Set imageData's pointer if necessary */
1606                 if (size > sizeof(SPC_LINK))
1607                 {
1608                     (*pLink)->u.pwszUrl =
1609                      (LPWSTR)((BYTE *)*pLink + sizeof(SPC_LINK));
1610                 }
1611                 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1612                  lpszStructType, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
1613                  *pLink, pcbStructInfo);
1614             }
1615         }
1616     }
1617     return ret;
1618 }
1619
1620 BOOL WINAPI WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType,
1621  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1622  void *pvStructInfo, DWORD *pcbStructInfo)
1623 {
1624     BOOL ret = FALSE;
1625
1626     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1627      pvStructInfo, *pcbStructInfo);
1628
1629     __TRY
1630     {
1631         struct AsnDecodeSequenceItem items[] = {
1632          { ASN_BITSTRING, offsetof(SPC_PE_IMAGE_DATA, Flags),
1633            CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1634            offsetof(SPC_PE_IMAGE_DATA, Flags.pbData), 0 },
1635          { ASN_CONSTRUCTOR | ASN_CONTEXT, offsetof(SPC_PE_IMAGE_DATA, pFile),
1636            CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE,
1637            offsetof(SPC_PE_IMAGE_DATA, pFile), 0 },
1638         };
1639
1640         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1641          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1642          pvStructInfo, pcbStructInfo, NULL);
1643     }
1644     __EXCEPT_PAGE_FAULT
1645     {
1646         SetLastError(STATUS_ACCESS_VIOLATION);
1647     }
1648     __ENDTRY
1649     TRACE("returning %d\n", ret);
1650     return ret;
1651 }
1652
1653 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType,
1654  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1655  void *pvStructInfo, DWORD *pcbStructInfo)
1656 {
1657     BOOL ret = TRUE;
1658     DWORD dataLen;
1659
1660     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1661      pvStructInfo, *pcbStructInfo);
1662
1663     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1664     {
1665         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1666         DWORD bytesNeeded = sizeof(LPSTR);
1667
1668         if (dataLen)
1669         {
1670             /* The largest possible string for the first two components
1671              * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1672              */
1673             char firstTwo[6];
1674             const BYTE *ptr;
1675
1676             snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1677              pbEncoded[1 + lenBytes] / 40,
1678              pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1679              * 40);
1680             bytesNeeded += strlen(firstTwo) + 1;
1681             for (ptr = pbEncoded + 2 + lenBytes; ret &&
1682              ptr - pbEncoded - 1 - lenBytes < dataLen; )
1683             {
1684                 /* large enough for ".4000000" */
1685                 char str[9];
1686                 int val = 0;
1687
1688                 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1689                  (*ptr & 0x80))
1690                 {
1691                     val <<= 7;
1692                     val |= *ptr & 0x7f;
1693                     ptr++;
1694                 }
1695                 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1696                  (*ptr & 0x80))
1697                 {
1698                     SetLastError(CRYPT_E_ASN1_CORRUPT);
1699                     ret = FALSE;
1700                 }
1701                 else
1702                 {
1703                     val <<= 7;
1704                     val |= *ptr++;
1705                     snprintf(str, sizeof(str), ".%d", val);
1706                     bytesNeeded += strlen(str);
1707                 }
1708             }
1709         }
1710         if (!pvStructInfo)
1711             *pcbStructInfo = bytesNeeded;
1712         else if (*pcbStructInfo < bytesNeeded)
1713         {
1714             *pcbStructInfo = bytesNeeded;
1715             SetLastError(ERROR_MORE_DATA);
1716             ret = FALSE;
1717         }
1718         else
1719         {
1720             if (dataLen)
1721             {
1722                 const BYTE *ptr;
1723                 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1724
1725                 *pszObjId = 0;
1726                 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1727                  pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1728                  40) * 40);
1729                 pszObjId += strlen(pszObjId);
1730                 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1731                  ptr - pbEncoded - 1 - lenBytes < dataLen; )
1732                 {
1733                     int val = 0;
1734
1735                     while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1736                      (*ptr & 0x80))
1737                     {
1738                         val <<= 7;
1739                         val |= *ptr & 0x7f;
1740                         ptr++;
1741                     }
1742                     val <<= 7;
1743                     val |= *ptr++;
1744                     sprintf(pszObjId, ".%d", val);
1745                     pszObjId += strlen(pszObjId);
1746                 }
1747             }
1748             else
1749                 *(LPSTR *)pvStructInfo = NULL;
1750             *pcbStructInfo = bytesNeeded;
1751         }
1752     }
1753     return ret;
1754 }
1755
1756 static BOOL WINAPI CRYPT_AsnDecodeOid(DWORD dwCertEncodingType,
1757  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1758  void *pvStructInfo, DWORD *pcbStructInfo)
1759 {
1760     BOOL ret = FALSE;
1761
1762     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1763      pvStructInfo, *pcbStructInfo);
1764
1765     if (!cbEncoded)
1766         SetLastError(CRYPT_E_ASN1_CORRUPT);
1767     else if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1768         ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, lpszStructType,
1769          pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
1770     else
1771         SetLastError(CRYPT_E_ASN1_BADTAG);
1772     return ret;
1773 }
1774
1775 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1776  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1777  void *pvStructInfo, DWORD *pcbStructInfo)
1778 {
1779     BOOL ret = TRUE;
1780     DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1781
1782     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1783      pvStructInfo, *pcbStructInfo);
1784
1785     if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1786         bytesNeeded += cbEncoded;
1787     if (!pvStructInfo)
1788         *pcbStructInfo = bytesNeeded;
1789     else if (*pcbStructInfo < bytesNeeded)
1790     {
1791         SetLastError(ERROR_MORE_DATA);
1792         *pcbStructInfo = bytesNeeded;
1793         ret = FALSE;
1794     }
1795     else
1796     {
1797         PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1798
1799         *pcbStructInfo = bytesNeeded;
1800         blob->cbData = cbEncoded;
1801         if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1802             blob->pbData = (LPBYTE)pbEncoded;
1803         else
1804         {
1805             assert(blob->pbData);
1806             memcpy(blob->pbData, pbEncoded, blob->cbData);
1807         }
1808     }
1809     return ret;
1810 }
1811
1812 static BOOL WINAPI CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType,
1813  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1814  void *pvStructInfo, DWORD *pcbStructInfo)
1815 {
1816     CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue =
1817      (CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
1818     struct AsnDecodeSequenceItem items[] = {
1819      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId),
1820        CRYPT_AsnDecodeOid, sizeof(LPSTR), FALSE, TRUE,
1821        offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId), 0 },
1822      { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value),
1823        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
1824        offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value.pbData), 0 },
1825     };
1826
1827     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1828      pvStructInfo, *pcbStructInfo);
1829
1830     return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1831      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1832      pvStructInfo, pcbStructInfo,
1833      typeValue ? typeValue->pszObjId : NULL);
1834 }
1835
1836 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1837  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1838  void *pvStructInfo, DWORD *pcbStructInfo)
1839 {
1840     CRYPT_ALGORITHM_IDENTIFIER *algo =
1841      (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
1842     BOOL ret = TRUE;
1843     struct AsnDecodeSequenceItem items[] = {
1844      { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
1845        CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1846        offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
1847      { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
1848        CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
1849        offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
1850     };
1851
1852     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1853      pvStructInfo, *pcbStructInfo);
1854
1855     ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1856      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1857      pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
1858     if (ret && pvStructInfo)
1859     {
1860         TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
1861          debugstr_a(algo->pszObjId));
1862     }
1863     return ret;
1864 }
1865
1866 static BOOL WINAPI CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType,
1867  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1868  void *pvStructInfo, DWORD *pcbStructInfo)
1869 {
1870     struct SPCDigest *digest =
1871      (struct SPCDigest *)pvStructInfo;
1872     struct AsnDecodeSequenceItem items[] = {
1873      { ASN_SEQUENCEOF, offsetof(struct SPCDigest, DigestAlgorithm),
1874        CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1875        FALSE, TRUE,
1876        offsetof(struct SPCDigest, DigestAlgorithm.pszObjId), 0 },
1877      { ASN_OCTETSTRING, offsetof(struct SPCDigest, Digest),
1878        CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
1879        FALSE, TRUE, offsetof(struct SPCDigest, Digest.pbData), 0 },
1880     };
1881
1882     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1883      pvStructInfo, *pcbStructInfo);
1884
1885     return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1886      sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1887      pvStructInfo, pcbStructInfo,
1888      digest ? digest->DigestAlgorithm.pszObjId : NULL);
1889 }
1890
1891 BOOL WINAPI WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType,
1892  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1893  void *pvStructInfo, DWORD *pcbStructInfo)
1894 {
1895     BOOL ret = FALSE;
1896
1897     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1898      pvStructInfo, *pcbStructInfo);
1899
1900     __TRY
1901     {
1902         struct AsnDecodeSequenceItem items[] = {
1903          { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, Data),
1904            CRYPT_AsnDecodeAttributeTypeValue,
1905            sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE), FALSE, TRUE,
1906            offsetof(SPC_INDIRECT_DATA_CONTENT, Data.pszObjId), 0 },
1907          { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm),
1908            CRYPT_AsnDecodeSPCDigest, sizeof(struct SPCDigest),
1909            FALSE, TRUE,
1910            offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm.pszObjId), 0 },
1911         };
1912
1913         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1914          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1915          pvStructInfo, pcbStructInfo, NULL);
1916     }
1917     __EXCEPT_PAGE_FAULT
1918     {
1919         SetLastError(STATUS_ACCESS_VIOLATION);
1920     }
1921     __ENDTRY
1922     TRACE("returning %d\n", ret);
1923     return ret;
1924 }
1925
1926 BOOL WINAPI WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType,
1927  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1928  void *pvStructInfo, DWORD *pcbStructInfo)
1929 {
1930     FIXME("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1931      pvStructInfo, *pcbStructInfo);
1932     return FALSE;
1933 }
1934
1935 static BOOL WINAPI CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType,
1936  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1937  void *pvStructInfo, DWORD *pcbStructInfo)
1938 {
1939     BOOL ret;
1940     DWORD bytesNeeded, dataLen;
1941
1942     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1943     {
1944         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1945
1946         bytesNeeded = dataLen + 2 + sizeof(LPWSTR);
1947         if (!pvStructInfo)
1948             *pcbStructInfo = bytesNeeded;
1949         else if (*pcbStructInfo < bytesNeeded)
1950         {
1951             *pcbStructInfo = bytesNeeded;
1952             SetLastError(ERROR_MORE_DATA);
1953             ret = FALSE;
1954         }
1955         else
1956         {
1957             LPWSTR str;
1958             DWORD i;
1959
1960             *pcbStructInfo = bytesNeeded;
1961             assert(pvStructInfo);
1962             str = *(LPWSTR *)pvStructInfo;
1963             for (i = 0; i < dataLen / 2; i++)
1964                 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1965                  pbEncoded[1 + lenBytes + 2 * i + 1];
1966             /* Decoded string is always NULL-terminated */
1967             str[i] = '\0';
1968         }
1969     }
1970     return ret;
1971 }
1972
1973 static BOOL CRYPT_AsnDecodeInteger(const BYTE *pbEncoded,
1974  DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo)
1975 {
1976     BOOL ret;
1977     DWORD bytesNeeded, dataLen;
1978
1979     if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1980     {
1981         BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1982
1983         bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
1984         if (!pvStructInfo)
1985             *pcbStructInfo = bytesNeeded;
1986         else if (*pcbStructInfo < bytesNeeded)
1987         {
1988             *pcbStructInfo = bytesNeeded;
1989             SetLastError(ERROR_MORE_DATA);
1990             ret = FALSE;
1991         }
1992         else
1993         {
1994             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
1995
1996             *pcbStructInfo = bytesNeeded;
1997             blob->cbData = dataLen;
1998             assert(blob->pbData);
1999             if (blob->cbData)
2000             {
2001                 DWORD i;
2002
2003                 for (i = 0; i < blob->cbData; i++)
2004                 {
2005                     blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2006                      dataLen - i - 1);
2007                 }
2008             }
2009         }
2010     }
2011     return ret;
2012 }
2013
2014 /* Ignores tag.  Only allows integers 4 bytes or smaller in size. */
2015 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2016  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2017  void *pvStructInfo, DWORD *pcbStructInfo)
2018 {
2019     BOOL ret;
2020     BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2021     CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2022     DWORD size = sizeof(buf);
2023
2024     blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2025     ret = CRYPT_AsnDecodeInteger(pbEncoded, cbEncoded, 0, buf, &size);
2026     if (ret)
2027     {
2028         if (!pvStructInfo)
2029             *pcbStructInfo = sizeof(int);
2030         else if (*pcbStructInfo < sizeof(int))
2031         {
2032             *pcbStructInfo = sizeof(int);
2033             SetLastError(ERROR_MORE_DATA);
2034             ret = FALSE;
2035         }
2036         else
2037         {
2038             int val, i;
2039
2040             *pcbStructInfo = sizeof(int);
2041             if (blob->pbData[blob->cbData - 1] & 0x80)
2042             {
2043                 /* initialize to a negative value to sign-extend */
2044                 val = -1;
2045             }
2046             else
2047                 val = 0;
2048             for (i = 0; i < blob->cbData; i++)
2049             {
2050                 val <<= 8;
2051                 val |= blob->pbData[blob->cbData - i - 1];
2052             }
2053             memcpy(pvStructInfo, &val, sizeof(int));
2054         }
2055     }
2056     else if (GetLastError() == ERROR_MORE_DATA)
2057         SetLastError(CRYPT_E_ASN1_LARGE);
2058     return ret;
2059 }
2060
2061 BOOL WINAPI WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType,
2062  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2063  void *pvStructInfo, DWORD *pcbStructInfo)
2064 {
2065     BOOL ret = FALSE;
2066
2067     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2068      pvStructInfo, *pcbStructInfo);
2069
2070     __TRY
2071     {
2072         struct AsnDecodeSequenceItem items[] = {
2073          { ASN_BMPSTRING, offsetof(CAT_MEMBERINFO, pwszSubjGuid),
2074            CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
2075            offsetof(CAT_MEMBERINFO, pwszSubjGuid), 0 },
2076          { ASN_INTEGER, offsetof(CAT_MEMBERINFO, dwCertVersion),
2077            CRYPT_AsnDecodeInt, sizeof(DWORD),
2078            FALSE, FALSE, 0, 0 },
2079         };
2080
2081         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2082          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2083          pvStructInfo, pcbStructInfo, NULL);
2084     }
2085     __EXCEPT_PAGE_FAULT
2086     {
2087         SetLastError(STATUS_ACCESS_VIOLATION);
2088     }
2089     __ENDTRY
2090     TRACE("returning %d\n", ret);
2091     return ret;
2092 }
2093
2094 BOOL WINAPI WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType,
2095  LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2096  void *pvStructInfo, DWORD *pcbStructInfo)
2097 {
2098     BOOL ret = FALSE;
2099
2100     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2101      pvStructInfo, *pcbStructInfo);
2102
2103     __TRY
2104     {
2105         struct AsnDecodeSequenceItem items[] = {
2106          { ASN_BMPSTRING, offsetof(CAT_NAMEVALUE, pwszTag),
2107            CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
2108            offsetof(CAT_NAMEVALUE, pwszTag), 0 },
2109          { ASN_INTEGER, offsetof(CAT_NAMEVALUE, fdwFlags),
2110            CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2111          { ASN_OCTETSTRING, offsetof(CAT_NAMEVALUE, Value),
2112            CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
2113            offsetof(CAT_NAMEVALUE, Value.pbData), 0 },
2114         };
2115
2116         ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2117          sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2118          pvStructInfo, pcbStructInfo, NULL);
2119     }
2120     __EXCEPT_PAGE_FAULT
2121     {
2122         SetLastError(STATUS_ACCESS_VIOLATION);
2123     }
2124     __ENDTRY
2125     TRACE("returning %d\n", ret);
2126     return ret;
2127 }