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