cmd: DIR command outputs free space for the path.
[wine.git] / dlls / wintrust / asn.c
blobf6c4086b5088bca4d144ff02a4300560cc243d0a
1 /* wintrust asn functions
3 * Copyright 2007 Juan Lang
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.
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.
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
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <assert.h>
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"
35 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
37 #ifdef WORDS_BIGENDIAN
39 #define hton16(x) (x)
40 #define n16toh(x) (x)
42 #else
44 #define hton16(x) RtlUshortByteSwap(x)
45 #define n16toh(x) RtlUshortByteSwap(x)
47 #endif
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)
53 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
55 DWORD bytesNeeded, significantBytes = 0;
57 if (len <= 0x7f)
58 bytesNeeded = 1;
59 else
61 DWORD temp;
63 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
64 temp <<= 8, significantBytes--)
66 bytesNeeded = significantBytes + 1;
68 if (!pbEncoded)
70 *pcbEncoded = bytesNeeded;
71 return TRUE;
73 if (*pcbEncoded < bytesNeeded)
75 SetLastError(ERROR_MORE_DATA);
76 return FALSE;
78 if (len <= 0x7f)
79 *pbEncoded = (BYTE)len;
80 else
82 DWORD i;
84 *pbEncoded++ = significantBytes | 0x80;
85 for (i = 0; i < significantBytes; i++)
87 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
88 len >>= 8;
91 *pcbEncoded = bytesNeeded;
92 return TRUE;
95 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
96 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
97 DWORD *pcbEncoded)
99 BOOL ret = TRUE;
100 const CRYPT_DATA_BLOB *blob = pvStructInfo;
101 DWORD bytesNeeded, lenBytes;
103 TRACE("(%ld, %p), %p, %ld\n", blob->cbData, blob->pbData, pbEncoded,
104 *pcbEncoded);
106 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
107 bytesNeeded = 1 + lenBytes + blob->cbData;
108 if (!pbEncoded)
109 *pcbEncoded = bytesNeeded;
110 else if (*pcbEncoded < bytesNeeded)
112 *pcbEncoded = bytesNeeded;
113 SetLastError(ERROR_MORE_DATA);
114 ret = FALSE;
116 else
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);
124 TRACE("returning %d\n", ret);
125 return ret;
128 BOOL WINAPI WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType,
129 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
130 DWORD *pcbEncoded)
132 BOOL ret = FALSE;
134 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType,
135 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
136 pcbEncoded);
138 __TRY
140 const SPC_LINK *link = pvStructInfo;
141 DWORD bytesNeeded, lenBytes;
143 switch (link->dwLinkChoice)
145 case SPC_FILE_LINK_CHOICE:
147 DWORD fileNameLen, fileNameLenBytes;
148 LPWSTR ptr;
150 fileNameLen = link->pwszFile ?
151 lstrlenW(link->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)
158 *pcbEncoded = bytesNeeded;
159 ret = TRUE;
161 else if (*pcbEncoded < bytesNeeded)
163 SetLastError(ERROR_MORE_DATA);
164 *pcbEncoded = bytesNeeded;
166 else
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->pwszFile; ptr && *ptr; ptr++)
178 *(WCHAR *)pbEncoded = hton16(*ptr);
179 pbEncoded += sizeof(WCHAR);
181 ret = TRUE;
183 break;
185 case SPC_MONIKER_LINK_CHOICE:
187 DWORD classIdLenBytes, dataLenBytes, dataLen;
188 CRYPT_DATA_BLOB classId = { sizeof(link->Moniker.ClassId),
189 (BYTE *)link->Moniker.ClassId };
191 CRYPT_EncodeLen(classId.cbData, NULL, &classIdLenBytes);
192 CRYPT_EncodeLen(link->Moniker.SerializedData.cbData, NULL,
193 &dataLenBytes);
194 dataLen = 2 + classIdLenBytes + classId.cbData +
195 dataLenBytes + link->Moniker.SerializedData.cbData;
196 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
197 bytesNeeded = 1 + dataLen + lenBytes;
198 if (!pbEncoded)
200 *pcbEncoded = bytesNeeded;
201 ret = TRUE;
203 else if (*pcbEncoded < bytesNeeded)
205 SetLastError(ERROR_MORE_DATA);
206 *pcbEncoded = bytesNeeded;
208 else
210 DWORD size;
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->Moniker.SerializedData.cbData;
221 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL,
222 &link->Moniker.SerializedData, pbEncoded, &size);
223 pbEncoded += size;
224 ret = TRUE;
226 break;
228 case SPC_URL_LINK_CHOICE:
230 LPWSTR ptr;
231 DWORD urlLen;
233 /* Check for invalid characters in URL */
234 ret = TRUE;
235 urlLen = 0;
236 for (ptr = link->pwszUrl; ptr && *ptr && ret; ptr++)
237 if (*ptr > 0x7f)
239 *pcbEncoded = 0;
240 SetLastError(CRYPT_E_INVALID_IA5_STRING);
241 ret = FALSE;
243 else
244 urlLen++;
245 if (ret)
247 CRYPT_EncodeLen(urlLen, NULL, &lenBytes);
248 bytesNeeded = 1 + lenBytes + urlLen;
249 if (!pbEncoded)
250 *pcbEncoded = bytesNeeded;
251 else if (*pcbEncoded < bytesNeeded)
253 SetLastError(ERROR_MORE_DATA);
254 *pcbEncoded = bytesNeeded;
255 ret = FALSE;
257 else
259 *pcbEncoded = bytesNeeded;
260 *pbEncoded++ = ASN_CONTEXT;
261 CRYPT_EncodeLen(urlLen, pbEncoded, &lenBytes);
262 pbEncoded += lenBytes;
263 for (ptr = link->pwszUrl; ptr && *ptr; ptr++)
264 *pbEncoded++ = (BYTE)*ptr;
267 break;
269 default:
270 SetLastError(E_INVALIDARG);
273 __EXCEPT_PAGE_FAULT
275 SetLastError(STATUS_ACCESS_VIOLATION);
277 __ENDTRY
278 TRACE("returning %d\n", ret);
279 return ret;
282 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
283 BYTE *, DWORD *);
285 struct AsnEncodeSequenceItem
287 const void *pvStructInfo;
288 CryptEncodeObjectFunc encodeFunc;
289 DWORD size; /* used during encoding, not for your use */
292 static BOOL CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
293 struct AsnEncodeSequenceItem items[], DWORD cItem, BYTE *pbEncoded,
294 DWORD *pcbEncoded)
296 BOOL ret;
297 DWORD i, dataLen = 0;
299 TRACE("%p, %ld, %p, %ld\n", items, cItem, pbEncoded, *pcbEncoded);
300 for (i = 0, ret = TRUE; ret && i < cItem; i++)
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;
309 if (ret)
311 DWORD lenBytes, bytesNeeded;
313 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
314 bytesNeeded = 1 + lenBytes + dataLen;
315 if (!pbEncoded)
316 *pcbEncoded = bytesNeeded;
317 else if (*pcbEncoded < bytesNeeded)
319 *pcbEncoded = bytesNeeded;
320 SetLastError(ERROR_MORE_DATA);
321 ret = FALSE;
323 else
325 *pcbEncoded = bytesNeeded;
326 *pbEncoded++ = ASN_SEQUENCE;
327 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
328 pbEncoded += lenBytes;
329 for (i = 0; ret && i < cItem; i++)
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;
340 TRACE("returning %d\n", ret);
341 return ret;
344 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
345 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
346 DWORD *pcbEncoded)
348 BOOL ret = FALSE;
350 __TRY
352 const CRYPT_BIT_BLOB *blob = pvStructInfo;
353 DWORD bytesNeeded, lenBytes, dataBytes;
354 BYTE unusedBits;
356 /* yep, MS allows cUnusedBits to be >= 8 */
357 if (!blob->cUnusedBits)
359 dataBytes = blob->cbData;
360 unusedBits = 0;
362 else if (blob->cbData * 8 > blob->cUnusedBits)
364 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
365 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
366 blob->cUnusedBits;
368 else
370 dataBytes = 0;
371 unusedBits = 0;
373 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
374 bytesNeeded = 1 + lenBytes + dataBytes + 1;
375 if (!pbEncoded)
377 *pcbEncoded = bytesNeeded;
378 ret = TRUE;
380 else if (*pcbEncoded < bytesNeeded)
382 *pcbEncoded = bytesNeeded;
383 SetLastError(ERROR_MORE_DATA);
385 else
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)
395 BYTE mask = 0xff << unusedBits;
397 if (dataBytes > 1)
399 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
400 pbEncoded += dataBytes - 1;
402 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
406 __EXCEPT_PAGE_FAULT
408 SetLastError(STATUS_ACCESS_VIOLATION);
410 __ENDTRY
411 return ret;
414 struct AsnConstructedItem
416 BYTE tag;
417 const void *pvStructInfo;
418 CryptEncodeObjectFunc encodeFunc;
421 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
422 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
423 DWORD *pcbEncoded)
425 BOOL ret;
426 const struct AsnConstructedItem *item = pvStructInfo;
427 DWORD len;
429 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
430 item->pvStructInfo, NULL, &len)))
432 DWORD dataLen, bytesNeeded;
434 CRYPT_EncodeLen(len, NULL, &dataLen);
435 bytesNeeded = 1 + dataLen + len;
436 if (!pbEncoded)
437 *pcbEncoded = bytesNeeded;
438 else if (*pcbEncoded < bytesNeeded)
440 *pcbEncoded = bytesNeeded;
441 SetLastError(ERROR_MORE_DATA);
442 ret = FALSE;
444 else
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)
454 /* Some functions propagate their errors through the size */
455 *pcbEncoded = len;
459 else
461 /* Some functions propagate their errors through the size */
462 *pcbEncoded = len;
464 return ret;
468 BOOL WINAPI WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType,
469 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
470 DWORD *pcbEncoded)
472 const SPC_PE_IMAGE_DATA *imageData = pvStructInfo;
473 BOOL ret = FALSE;
475 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType,
476 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
477 pcbEncoded);
479 __TRY
481 struct AsnEncodeSequenceItem items[2] = {
482 { 0 }
484 struct AsnConstructedItem constructed = { 0, imageData->pFile,
485 WVTAsn1SpcLinkEncode };
486 DWORD cItem = 0;
488 if (imageData->Flags.cbData)
490 items[cItem].pvStructInfo = &imageData->Flags;
491 items[cItem].encodeFunc = CRYPT_AsnEncodeBits;
492 cItem++;
494 if (imageData->pFile)
496 items[cItem].pvStructInfo = &constructed;
497 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
498 cItem++;
501 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
502 pbEncoded, pcbEncoded);
504 __EXCEPT_PAGE_FAULT
506 SetLastError(STATUS_ACCESS_VIOLATION);
508 __ENDTRY
509 TRACE("returning %d\n", ret);
510 return ret;
513 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
514 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
515 DWORD *pcbEncoded)
517 LPCSTR pszObjId = pvStructInfo;
518 DWORD bytesNeeded = 0, lenBytes;
519 BOOL ret = TRUE;
520 int firstPos = 0;
521 BYTE firstByte = 0;
523 TRACE("%s\n", debugstr_a(pszObjId));
525 if (pszObjId)
527 const char *ptr;
528 int val1, val2;
530 if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2)
532 SetLastError(CRYPT_E_ASN1_ERROR);
533 return FALSE;
535 bytesNeeded++;
536 firstByte = val1 * 40 + val2;
537 ptr = pszObjId + firstPos;
538 if (*ptr == '.')
540 ptr++;
541 firstPos++;
543 while (ret && *ptr)
545 int pos;
547 /* note I assume each component is at most 32-bits long in base 2 */
548 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
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++;
564 else
566 SetLastError(CRYPT_E_ASN1_ERROR);
567 return FALSE;
570 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
572 else
573 lenBytes = 1;
574 bytesNeeded += 1 + lenBytes;
575 if (pbEncoded)
577 if (*pcbEncoded < bytesNeeded)
579 SetLastError(ERROR_MORE_DATA);
580 ret = FALSE;
582 else
584 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
585 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
586 pbEncoded += lenBytes;
587 if (pszObjId)
589 const char *ptr;
590 int val, pos;
592 *pbEncoded++ = firstByte;
593 ptr = pszObjId + firstPos;
594 while (ret && *ptr)
596 sscanf(ptr, "%d%n", &val, &pos);
598 unsigned char outBytes[5];
599 int numBytes, i;
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--)
613 outBytes[i - 1] = val & 0x7f;
614 val >>= 7;
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++;
627 *pcbEncoded = bytesNeeded;
628 return ret;
631 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
632 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
633 DWORD *pcbEncoded)
635 const CRYPT_DER_BLOB *blob = pvStructInfo;
636 BOOL ret = TRUE;
638 if (!pbEncoded)
639 *pcbEncoded = blob->cbData;
640 else if (*pcbEncoded < blob->cbData)
642 *pcbEncoded = blob->cbData;
643 SetLastError(ERROR_MORE_DATA);
644 ret = FALSE;
646 else
648 if (blob->cbData)
649 memcpy(pbEncoded, blob->pbData, blob->cbData);
650 *pcbEncoded = blob->cbData;
652 return ret;
655 /* Different from the one in crypt32 */
656 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
657 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
658 BYTE *pbEncoded, DWORD *pcbEncoded)
660 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
661 static const BYTE asn1Null[] = { ASN_NULL, 0 };
662 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
663 (LPBYTE)asn1Null };
664 BOOL ret;
665 struct AsnEncodeSequenceItem items[2] = {
666 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
667 { NULL, CRYPT_CopyEncodedBlob, 0 },
669 DWORD cItem = 2;
671 if (algo->Parameters.cbData)
672 items[1].pvStructInfo = &algo->Parameters;
673 else if (algo->pszObjId)
674 items[1].pvStructInfo = &nullBlob;
675 else
676 cItem -= 1;
677 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
678 pbEncoded, pcbEncoded);
679 return ret;
682 static BOOL WINAPI CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType,
683 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
684 DWORD *pcbEncoded)
686 const CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue = pvStructInfo;
687 struct AsnEncodeSequenceItem items[] = {
688 { typeValue->pszObjId, CRYPT_AsnEncodeOid, 0 },
689 { &typeValue->Value, CRYPT_CopyEncodedBlob, 0 },
692 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items),
693 pbEncoded, pcbEncoded);
696 struct SPCDigest
698 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm;
699 CRYPT_HASH_BLOB Digest;
702 static BOOL WINAPI CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType,
703 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
704 DWORD *pcbEncoded)
706 const struct SPCDigest *digest = pvStructInfo;
707 struct AsnEncodeSequenceItem items[] = {
708 { &digest->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
709 { &digest->Digest, CRYPT_AsnEncodeOctets, 0 },
712 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items),
713 pbEncoded, pcbEncoded);
716 BOOL WINAPI WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType,
717 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
718 DWORD *pcbEncoded)
720 BOOL ret = FALSE;
722 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType,
723 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
725 __TRY
727 const SPC_INDIRECT_DATA_CONTENT *data = pvStructInfo;
728 struct AsnEncodeSequenceItem items[] = {
729 { &data->Data, CRYPT_AsnEncodeAttributeTypeValue, 0 },
730 { &data->DigestAlgorithm, CRYPT_AsnEncodeSPCDigest, 0 },
733 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items),
734 pbEncoded, pcbEncoded);
736 __EXCEPT_PAGE_FAULT
738 SetLastError(STATUS_ACCESS_VIOLATION);
740 __ENDTRY
741 return ret;
744 static BOOL WINAPI CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType,
745 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
746 DWORD *pcbEncoded)
748 BOOL ret = TRUE;
749 LPCWSTR str = pvStructInfo;
750 DWORD bytesNeeded, lenBytes, strLen;
752 if (str)
753 strLen = lstrlenW(str);
754 else
755 strLen = 0;
756 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
757 bytesNeeded = 1 + lenBytes + strLen * 2;
758 if (!pbEncoded)
759 *pcbEncoded = bytesNeeded;
760 else if (*pcbEncoded < bytesNeeded)
762 *pcbEncoded = bytesNeeded;
763 SetLastError(ERROR_MORE_DATA);
764 ret = FALSE;
766 else
768 DWORD i;
770 *pcbEncoded = bytesNeeded;
771 *pbEncoded++ = ASN_BMPSTRING;
772 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
773 pbEncoded += lenBytes;
774 for (i = 0; i < strLen; i++)
776 *pbEncoded++ = (str[i] & 0xff00) >> 8;
777 *pbEncoded++ = str[i] & 0x00ff;
780 return ret;
783 struct AsnEncodeTagSwappedItem
785 BYTE tag;
786 const void *pvStructInfo;
787 CryptEncodeObjectFunc encodeFunc;
790 /* Sort of a wacky hack, it encodes something using the struct
791 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
792 * given in the struct AsnEncodeTagSwappedItem.
794 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
795 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
796 DWORD *pcbEncoded)
798 BOOL ret;
799 const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
801 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
802 item->pvStructInfo, pbEncoded, pcbEncoded);
803 if (ret && pbEncoded)
804 *pbEncoded = item->tag;
805 return ret;
808 BOOL WINAPI WVTAsn1SpcSpOpusInfoEncode(DWORD dwCertEncodingType,
809 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
810 DWORD *pcbEncoded)
812 BOOL ret = FALSE;
814 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType,
815 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
817 __TRY
819 const SPC_SP_OPUS_INFO *info = pvStructInfo;
821 if (info->pMoreInfo &&
822 info->pMoreInfo->dwLinkChoice != SPC_URL_LINK_CHOICE &&
823 info->pMoreInfo->dwLinkChoice != SPC_MONIKER_LINK_CHOICE &&
824 info->pMoreInfo->dwLinkChoice != SPC_FILE_LINK_CHOICE)
825 SetLastError(E_INVALIDARG);
826 else if (info->pPublisherInfo &&
827 info->pPublisherInfo->dwLinkChoice != SPC_URL_LINK_CHOICE &&
828 info->pPublisherInfo->dwLinkChoice != SPC_MONIKER_LINK_CHOICE &&
829 info->pPublisherInfo->dwLinkChoice != SPC_FILE_LINK_CHOICE)
830 SetLastError(E_INVALIDARG);
831 else
833 struct AsnEncodeSequenceItem items[3] = { { 0 } };
834 struct AsnConstructedItem constructed[3] = { { 0 } };
835 struct AsnEncodeTagSwappedItem swapped;
836 DWORD cItem = 0, cConstructed = 0;
838 if (info->pwszProgramName)
840 swapped.tag = ASN_CONTEXT;
841 swapped.pvStructInfo = info->pwszProgramName;
842 swapped.encodeFunc = CRYPT_AsnEncodeBMPString;
843 constructed[cConstructed].tag = 0;
844 constructed[cConstructed].pvStructInfo = &swapped;
845 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeSwapTag;
846 items[cItem].pvStructInfo = &constructed[cConstructed];
847 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
848 cConstructed++;
849 cItem++;
851 if (info->pMoreInfo)
853 constructed[cConstructed].tag = 1;
854 constructed[cConstructed].pvStructInfo = info->pMoreInfo;
855 constructed[cConstructed].encodeFunc = WVTAsn1SpcLinkEncode;
856 items[cItem].pvStructInfo = &constructed[cConstructed];
857 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
858 cConstructed++;
859 cItem++;
861 if (info->pPublisherInfo)
863 constructed[cConstructed].tag = 2;
864 constructed[cConstructed].pvStructInfo = info->pPublisherInfo;
865 constructed[cConstructed].encodeFunc = WVTAsn1SpcLinkEncode;
866 items[cItem].pvStructInfo = &constructed[cConstructed];
867 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
868 cConstructed++;
869 cItem++;
871 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
872 items, cItem, pbEncoded, pcbEncoded);
875 __EXCEPT_PAGE_FAULT
877 SetLastError(STATUS_ACCESS_VIOLATION);
879 __ENDTRY
880 return ret;
883 static BOOL CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
884 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
885 DWORD *pcbEncoded)
887 BOOL ret;
889 __TRY
891 DWORD significantBytes, lenBytes, bytesNeeded;
892 BYTE padByte = 0;
893 BOOL pad = FALSE;
894 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
896 significantBytes = blob->cbData;
897 if (significantBytes)
899 if (blob->pbData[significantBytes - 1] & 0x80)
901 /* negative, lop off leading (little-endian) 0xffs */
902 for (; significantBytes > 0 &&
903 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
905 if (blob->pbData[significantBytes - 1] < 0x80)
907 padByte = 0xff;
908 pad = TRUE;
911 else
913 /* positive, lop off leading (little-endian) zeroes */
914 for (; significantBytes > 0 &&
915 !blob->pbData[significantBytes - 1]; significantBytes--)
917 if (significantBytes == 0)
918 significantBytes = 1;
919 if (blob->pbData[significantBytes - 1] > 0x7f)
921 padByte = 0;
922 pad = TRUE;
926 if (pad)
927 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
928 else
929 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
930 bytesNeeded = 1 + lenBytes + significantBytes;
931 if (pad)
932 bytesNeeded++;
933 if (!pbEncoded)
935 *pcbEncoded = bytesNeeded;
936 ret = TRUE;
938 else if (*pcbEncoded < bytesNeeded)
940 *pcbEncoded = bytesNeeded;
941 SetLastError(ERROR_MORE_DATA);
942 ret = FALSE;
944 else
946 *pcbEncoded = bytesNeeded;
947 *pbEncoded++ = ASN_INTEGER;
948 if (pad)
950 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
951 pbEncoded += lenBytes;
952 *pbEncoded++ = padByte;
954 else
956 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
957 pbEncoded += lenBytes;
959 for (; significantBytes > 0; significantBytes--)
960 *(pbEncoded++) = blob->pbData[significantBytes - 1];
961 ret = TRUE;
964 __EXCEPT_PAGE_FAULT
966 SetLastError(STATUS_ACCESS_VIOLATION);
967 ret = FALSE;
969 __ENDTRY
970 return ret;
973 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
974 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
975 DWORD *pcbEncoded)
977 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
979 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
980 &blob, pbEncoded, pcbEncoded);
983 BOOL WINAPI WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType,
984 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
985 DWORD *pcbEncoded)
987 BOOL ret = FALSE;
989 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType,
990 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
992 __TRY
994 const CAT_MEMBERINFO *info = pvStructInfo;
995 struct AsnEncodeSequenceItem items[] = {
996 { info->pwszSubjGuid, CRYPT_AsnEncodeBMPString, 0 },
997 { &info->dwCertVersion, CRYPT_AsnEncodeInt, 0 },
1000 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items),
1001 pbEncoded, pcbEncoded);
1003 __EXCEPT_PAGE_FAULT
1005 SetLastError(STATUS_ACCESS_VIOLATION);
1007 __ENDTRY
1008 return ret;
1011 BOOL WINAPI WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType,
1012 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
1013 DWORD *pcbEncoded)
1015 BOOL ret = FALSE;
1017 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType,
1018 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
1020 __TRY
1022 const CAT_NAMEVALUE *value = pvStructInfo;
1023 struct AsnEncodeSequenceItem items[] = {
1024 { value->pwszTag, CRYPT_AsnEncodeBMPString, 0 },
1025 { &value->fdwFlags, CRYPT_AsnEncodeInt, 0 },
1026 { &value->Value, CRYPT_AsnEncodeOctets, 0 },
1029 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items),
1030 pbEncoded, pcbEncoded);
1032 __EXCEPT_PAGE_FAULT
1034 SetLastError(STATUS_ACCESS_VIOLATION);
1036 __ENDTRY
1037 return ret;
1040 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1041 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
1042 DWORD *pcbEncoded)
1044 BOOL val = *(const BOOL *)pvStructInfo, ret;
1046 TRACE("%d\n", val);
1048 if (!pbEncoded)
1050 *pcbEncoded = 3;
1051 ret = TRUE;
1053 else if (*pcbEncoded < 3)
1055 *pcbEncoded = 3;
1056 SetLastError(ERROR_MORE_DATA);
1057 ret = FALSE;
1059 else
1061 *pcbEncoded = 3;
1062 *pbEncoded++ = ASN_BOOL;
1063 *pbEncoded++ = 1;
1064 *pbEncoded++ = val ? 0xff : 0;
1065 ret = TRUE;
1067 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1068 return ret;
1071 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoEncode(DWORD dwCertEncodingType,
1072 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
1073 DWORD *pcbEncoded)
1075 BOOL ret = FALSE;
1077 TRACE("(0x%08lx, %s, %p, %p, %p)\n", dwCertEncodingType,
1078 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
1080 __TRY
1082 const SPC_FINANCIAL_CRITERIA *criteria = pvStructInfo;
1083 struct AsnEncodeSequenceItem items[] = {
1084 { &criteria->fFinancialInfoAvailable, CRYPT_AsnEncodeBool, 0 },
1085 { &criteria->fMeetsCriteria, CRYPT_AsnEncodeBool, 0 },
1088 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, ARRAY_SIZE(items),
1089 pbEncoded, pcbEncoded);
1091 __EXCEPT_PAGE_FAULT
1093 SetLastError(STATUS_ACCESS_VIOLATION);
1095 __ENDTRY
1096 return ret;
1099 /* Gets the number of length bytes from the given (leading) length byte */
1100 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
1102 /* Helper function to get the encoded length of the data starting at pbEncoded,
1103 * where pbEncoded[0] is the tag. If the data are too short to contain a
1104 * length or if the length is too large for cbEncoded, sets an appropriate
1105 * error code and returns FALSE.
1107 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
1109 BOOL ret;
1111 if (cbEncoded <= 1)
1113 SetLastError(CRYPT_E_ASN1_CORRUPT);
1114 ret = FALSE;
1116 else if (pbEncoded[1] <= 0x7f)
1118 if (pbEncoded[1] + 1 > cbEncoded)
1120 SetLastError(CRYPT_E_ASN1_EOD);
1121 ret = FALSE;
1123 else
1125 *len = pbEncoded[1];
1126 ret = TRUE;
1129 else if (pbEncoded[1] == 0x80)
1131 FIXME("unimplemented for indefinite-length encoding\n");
1132 SetLastError(CRYPT_E_ASN1_CORRUPT);
1133 ret = FALSE;
1135 else
1137 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
1139 if (lenLen > sizeof(DWORD) + 1)
1141 SetLastError(CRYPT_E_ASN1_LARGE);
1142 ret = FALSE;
1144 else if (lenLen + 2 > cbEncoded)
1146 SetLastError(CRYPT_E_ASN1_CORRUPT);
1147 ret = FALSE;
1149 else
1151 DWORD out = 0;
1153 pbEncoded += 2;
1154 while (--lenLen)
1156 out <<= 8;
1157 out |= *pbEncoded++;
1159 if (out + lenLen + 1 > cbEncoded)
1161 SetLastError(CRYPT_E_ASN1_EOD);
1162 ret = FALSE;
1164 else
1166 *len = out;
1167 ret = TRUE;
1171 return ret;
1174 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
1175 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1176 void *pvStructInfo, DWORD *pcbStructInfo)
1178 BOOL ret;
1179 DWORD bytesNeeded, dataLen;
1181 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1182 pvStructInfo, *pcbStructInfo);
1184 if (!cbEncoded)
1186 SetLastError(CRYPT_E_ASN1_CORRUPT);
1187 ret = FALSE;
1189 else if (pbEncoded[0] != ASN_OCTETSTRING)
1191 SetLastError(CRYPT_E_ASN1_BADTAG);
1192 ret = FALSE;
1194 else if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1196 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1197 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
1198 else
1199 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
1200 if (!pvStructInfo)
1201 *pcbStructInfo = bytesNeeded;
1202 else if (*pcbStructInfo < bytesNeeded)
1204 SetLastError(ERROR_MORE_DATA);
1205 *pcbStructInfo = bytesNeeded;
1206 ret = FALSE;
1208 else
1210 CRYPT_DATA_BLOB *blob;
1211 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1213 blob = pvStructInfo;
1214 blob->cbData = dataLen;
1215 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1216 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
1217 else
1219 assert(blob->pbData);
1220 if (blob->cbData)
1221 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
1222 blob->cbData);
1226 return ret;
1229 static BOOL CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType,
1230 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1231 void *pvStructInfo, DWORD *pcbStructInfo)
1233 BOOL ret = FALSE;
1234 DWORD bytesNeeded = sizeof(SPC_LINK), dataLen;
1236 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1237 pvStructInfo, *pcbStructInfo);
1239 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1241 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1242 DWORD realDataLen;
1244 switch (pbEncoded[0])
1246 case ASN_CONTEXT:
1247 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1248 if (!pvStructInfo)
1249 *pcbStructInfo = bytesNeeded;
1250 else if (*pcbStructInfo < bytesNeeded)
1252 *pcbStructInfo = bytesNeeded;
1253 SetLastError(ERROR_MORE_DATA);
1254 ret = FALSE;
1256 else
1258 PSPC_LINK link = pvStructInfo;
1259 DWORD i;
1261 link->dwLinkChoice = SPC_URL_LINK_CHOICE;
1262 for (i = 0; i < dataLen; i++)
1263 link->pwszUrl[i] =
1264 *(pbEncoded + 1 + lenBytes + i);
1265 link->pwszUrl[i] = '\0';
1266 TRACE("returning url %s\n", debugstr_w(link->pwszUrl));
1268 break;
1269 case ASN_CONSTRUCTOR | ASN_CONTEXT | 1:
1271 CRYPT_DATA_BLOB classId;
1272 DWORD size = sizeof(classId);
1274 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
1275 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
1276 CRYPT_DECODE_NOCOPY_FLAG, &classId, &size)))
1278 if (classId.cbData != sizeof(SPC_UUID))
1280 SetLastError(CRYPT_E_BAD_ENCODE);
1281 ret = FALSE;
1283 else
1285 CRYPT_DATA_BLOB data;
1287 /* The tag length for the classId must be 1 since the
1288 * length is correct.
1290 size = sizeof(data);
1291 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
1292 pbEncoded + 3 + lenBytes + classId.cbData,
1293 cbEncoded - 3 - lenBytes - classId.cbData,
1294 CRYPT_DECODE_NOCOPY_FLAG, &data, &size)))
1296 bytesNeeded += data.cbData;
1297 if (!pvStructInfo)
1298 *pcbStructInfo = bytesNeeded;
1299 else if (*pcbStructInfo < bytesNeeded)
1301 *pcbStructInfo = bytesNeeded;
1302 SetLastError(ERROR_MORE_DATA);
1303 ret = FALSE;
1305 else
1307 PSPC_LINK link = pvStructInfo;
1309 link->dwLinkChoice = SPC_MONIKER_LINK_CHOICE;
1310 /* pwszFile pointer was set by caller, copy it
1311 * before overwriting it
1313 link->Moniker.SerializedData.pbData =
1314 (BYTE *)link->pwszFile;
1315 memcpy(link->Moniker.ClassId, classId.pbData,
1316 classId.cbData);
1317 memcpy(link->Moniker.SerializedData.pbData,
1318 data.pbData, data.cbData);
1319 link->Moniker.SerializedData.cbData = data.cbData;
1324 break;
1326 case ASN_CONSTRUCTOR | ASN_CONTEXT | 2:
1327 if (dataLen && pbEncoded[1 + lenBytes] != ASN_CONTEXT)
1328 SetLastError(CRYPT_E_ASN1_BADTAG);
1329 else if ((ret = CRYPT_GetLen(pbEncoded + 1 + lenBytes, dataLen,
1330 &realDataLen)))
1332 BYTE realLenBytes = GET_LEN_BYTES(pbEncoded[2 + lenBytes]);
1334 bytesNeeded += realDataLen + sizeof(WCHAR);
1335 if (!pvStructInfo)
1336 *pcbStructInfo = bytesNeeded;
1337 else if (*pcbStructInfo < bytesNeeded)
1339 *pcbStructInfo = bytesNeeded;
1340 SetLastError(ERROR_MORE_DATA);
1341 ret = FALSE;
1343 else
1345 PSPC_LINK link = pvStructInfo;
1346 DWORD i;
1347 const BYTE *ptr = pbEncoded + 2 + lenBytes + realLenBytes;
1349 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1350 for (i = 0; i < dataLen / sizeof(WCHAR); i++)
1351 link->pwszFile[i] =
1352 hton16(*(const WORD *)(ptr + i * sizeof(WCHAR)));
1353 link->pwszFile[realDataLen / sizeof(WCHAR)] = '\0';
1354 TRACE("returning file %s\n", debugstr_w(link->pwszFile));
1357 else
1359 bytesNeeded += sizeof(WCHAR);
1360 if (!pvStructInfo)
1361 *pcbStructInfo = bytesNeeded;
1362 else if (*pcbStructInfo < bytesNeeded)
1364 *pcbStructInfo = bytesNeeded;
1365 SetLastError(ERROR_MORE_DATA);
1366 ret = FALSE;
1368 else
1370 PSPC_LINK link = pvStructInfo;
1372 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1373 link->pwszFile[0] = '\0';
1374 ret = TRUE;
1377 break;
1378 default:
1379 SetLastError(CRYPT_E_ASN1_BADTAG);
1382 TRACE("returning %d\n", ret);
1383 return ret;
1386 BOOL WINAPI WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType,
1387 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1388 void *pvStructInfo, DWORD *pcbStructInfo)
1390 BOOL ret = FALSE;
1392 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1393 pvStructInfo, *pcbStructInfo);
1395 __TRY
1397 DWORD bytesNeeded;
1399 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1400 lpszStructType, pbEncoded, cbEncoded, dwFlags, NULL, &bytesNeeded);
1401 if (ret)
1403 if (!pvStructInfo)
1404 *pcbStructInfo = bytesNeeded;
1405 else if (*pcbStructInfo < bytesNeeded)
1407 *pcbStructInfo = bytesNeeded;
1408 SetLastError(ERROR_MORE_DATA);
1409 ret = FALSE;
1411 else
1413 SPC_LINK *link = pvStructInfo;
1415 link->pwszFile =
1416 (LPWSTR)((BYTE *)pvStructInfo + sizeof(SPC_LINK));
1417 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1418 lpszStructType, pbEncoded, cbEncoded, dwFlags, pvStructInfo,
1419 pcbStructInfo);
1423 __EXCEPT_PAGE_FAULT
1425 SetLastError(STATUS_ACCESS_VIOLATION);
1427 __ENDTRY
1428 TRACE("returning %d\n", ret);
1429 return ret;
1432 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
1433 DWORD, DWORD, void *, DWORD *);
1435 /* tag:
1436 * The expected tag of the item. If tag is 0, decodeFunc is called
1437 * regardless of the tag value seen.
1438 * offset:
1439 * A sequence is decoded into a struct. The offset member is the
1440 * offset of this item within that struct.
1441 * decodeFunc:
1442 * The decoder function to use. If this is NULL, then the member isn't
1443 * decoded, but minSize space is reserved for it.
1444 * minSize:
1445 * The minimum amount of space occupied after decoding. You must set this.
1446 * optional:
1447 * If true, and the tag doesn't match the expected tag for this item,
1448 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1449 * filled with 0 for this member.
1450 * hasPointer, pointerOffset:
1451 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1452 * the offset within the struct of the data pointer (or to the
1453 * first data pointer, if more than one exist).
1454 * size:
1455 * Used by CRYPT_AsnDecodeSequence, not for your use.
1457 struct AsnDecodeSequenceItem
1459 BYTE tag;
1460 DWORD offset;
1461 CryptDecodeObjectFunc decodeFunc;
1462 DWORD minSize;
1463 BOOL optional;
1464 BOOL hasPointer;
1465 DWORD pointerOffset;
1466 DWORD size;
1469 /* Align up to a DWORD_PTR boundary
1471 #define ALIGN_DWORD_PTR(x) (((x) + sizeof(DWORD_PTR) - 1) & ~(sizeof(DWORD_PTR) - 1))
1473 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
1474 #define MEMBERSIZE(s, member, nextmember) \
1475 (offsetof(s, nextmember) - offsetof(s, member))
1478 /* Decodes the items in a sequence, where the items are described in items,
1479 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
1480 * pvStructInfo. nextData is a pointer to the memory location at which the
1481 * first decoded item with a dynamic pointer should point.
1482 * Upon decoding, *cbDecoded is the total number of bytes decoded.
1484 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
1485 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1486 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
1487 DWORD *cbDecoded)
1489 BOOL ret;
1490 DWORD i, decoded = 0;
1491 const BYTE *ptr = pbEncoded;
1493 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %p\n", items, cItem, pbEncoded,
1494 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
1496 for (i = 0, ret = TRUE; ret && i < cItem; i++)
1498 if (cbEncoded - (ptr - pbEncoded) != 0)
1500 DWORD nextItemLen;
1502 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
1503 &nextItemLen)))
1505 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
1507 if (ptr[0] == items[i].tag || !items[i].tag)
1509 if (nextData && pvStructInfo && items[i].hasPointer)
1511 TRACE("Setting next pointer to %p\n",
1512 nextData);
1513 *(BYTE **)((BYTE *)pvStructInfo +
1514 items[i].pointerOffset) = nextData;
1516 if (items[i].decodeFunc)
1518 if (pvStructInfo)
1519 TRACE("decoding item %ld\n", i);
1520 else
1521 TRACE("sizing item %ld\n", i);
1522 ret = items[i].decodeFunc(dwCertEncodingType,
1523 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
1524 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
1525 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
1526 : NULL, &items[i].size);
1527 if (ret)
1529 if (items[i].size < items[i].minSize)
1530 items[i].size = items[i].minSize;
1531 else if (items[i].size > items[i].minSize)
1533 /* Account for alignment padding */
1534 items[i].size = ALIGN_DWORD_PTR(items[i].size);
1536 TRACE("item %ld size: %ld\n", i, items[i].size);
1537 if (nextData && items[i].hasPointer &&
1538 items[i].size > items[i].minSize)
1539 nextData += items[i].size - items[i].minSize;
1540 ptr += 1 + nextItemLenBytes + nextItemLen;
1541 decoded += 1 + nextItemLenBytes + nextItemLen;
1542 TRACE("item %ld: decoded %ld bytes\n", i,
1543 1 + nextItemLenBytes + nextItemLen);
1545 else if (items[i].optional &&
1546 GetLastError() == CRYPT_E_ASN1_BADTAG)
1548 TRACE("skipping optional item %ld\n", i);
1549 items[i].size = items[i].minSize;
1550 SetLastError(NOERROR);
1551 ret = TRUE;
1553 else
1554 TRACE("item %ld failed: %08lx\n", i,
1555 GetLastError());
1557 else
1559 TRACE("item %ld: decoded %ld bytes\n", i,
1560 1 + nextItemLenBytes + nextItemLen);
1561 ptr += 1 + nextItemLenBytes + nextItemLen;
1562 decoded += 1 + nextItemLenBytes + nextItemLen;
1563 items[i].size = items[i].minSize;
1566 else if (items[i].optional)
1568 TRACE("skipping optional item %ld\n", i);
1569 items[i].size = items[i].minSize;
1571 else
1573 TRACE("item %ld: tag %02x doesn't match expected %02x\n",
1574 i, ptr[0], items[i].tag);
1575 SetLastError(CRYPT_E_ASN1_BADTAG);
1576 ret = FALSE;
1580 else if (items[i].optional)
1582 TRACE("missing optional item %ld, skipping\n", i);
1583 items[i].size = items[i].minSize;
1585 else
1587 TRACE("not enough bytes for item %ld, failing\n", i);
1588 SetLastError(CRYPT_E_ASN1_CORRUPT);
1589 ret = FALSE;
1592 if (ret)
1593 *cbDecoded = decoded;
1594 TRACE("returning %d\n", ret);
1595 return ret;
1598 /* This decodes an arbitrary sequence into a contiguous block of memory
1599 * (basically, a struct.) Each element being decoded is described by a struct
1600 * AsnDecodeSequenceItem, see above.
1601 * startingPointer is an optional pointer to the first place where dynamic
1602 * data will be stored. If you know the starting offset, you may pass it
1603 * here. Otherwise, pass NULL, and one will be inferred from the items.
1605 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
1606 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1607 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1608 void *startingPointer)
1610 BOOL ret;
1612 TRACE("%p, %ld, %p, %ld, %08lx, %p, %ld, %p\n", items, cItem, pbEncoded,
1613 cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, startingPointer);
1615 if (pbEncoded[0] == ASN_SEQUENCE)
1617 DWORD dataLen;
1619 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1621 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
1622 const BYTE *ptr = pbEncoded + 1 + lenBytes;
1624 cbEncoded -= 1 + lenBytes;
1625 if (cbEncoded < dataLen)
1627 TRACE("dataLen %ld exceeds cbEncoded %ld, failing\n", dataLen,
1628 cbEncoded);
1629 SetLastError(CRYPT_E_ASN1_CORRUPT);
1630 ret = FALSE;
1632 else
1633 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
1634 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
1635 if (ret && cbDecoded != dataLen)
1637 TRACE("expected %ld decoded, got %ld, failing\n", dataLen,
1638 cbDecoded);
1639 SetLastError(CRYPT_E_ASN1_CORRUPT);
1640 ret = FALSE;
1642 if (ret)
1644 DWORD i, bytesNeeded = 0, structSize = 0;
1646 for (i = 0; i < cItem; i++)
1648 bytesNeeded += items[i].size;
1649 structSize += items[i].minSize;
1651 if (!pvStructInfo)
1652 *pcbStructInfo = bytesNeeded;
1653 else if (*pcbStructInfo < bytesNeeded)
1655 SetLastError(ERROR_MORE_DATA);
1656 *pcbStructInfo = bytesNeeded;
1657 ret = FALSE;
1659 else
1661 BYTE *nextData;
1663 *pcbStructInfo = bytesNeeded;
1664 if (startingPointer)
1665 nextData = startingPointer;
1666 else
1667 nextData = (BYTE *)pvStructInfo + structSize;
1668 memset(pvStructInfo, 0, structSize);
1669 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
1670 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
1671 &cbDecoded);
1676 else
1678 SetLastError(CRYPT_E_ASN1_BADTAG);
1679 ret = FALSE;
1681 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1682 return ret;
1685 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
1686 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1687 void *pvStructInfo, DWORD *pcbStructInfo)
1689 BOOL ret;
1691 TRACE("(%p, %ld, 0x%08lx, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
1692 pvStructInfo, *pcbStructInfo);
1694 if (pbEncoded[0] == ASN_BITSTRING)
1696 DWORD bytesNeeded, dataLen;
1698 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1700 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1701 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
1702 else
1703 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
1704 if (!pvStructInfo)
1705 *pcbStructInfo = bytesNeeded;
1706 else if (*pcbStructInfo < bytesNeeded)
1708 *pcbStructInfo = bytesNeeded;
1709 SetLastError(ERROR_MORE_DATA);
1710 ret = FALSE;
1712 else
1714 CRYPT_BIT_BLOB *blob;
1716 blob = pvStructInfo;
1717 blob->cbData = dataLen - 1;
1718 blob->cUnusedBits = *(pbEncoded + 1 +
1719 GET_LEN_BYTES(pbEncoded[1]));
1720 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1722 blob->pbData = (BYTE *)pbEncoded + 2 +
1723 GET_LEN_BYTES(pbEncoded[1]);
1725 else
1727 assert(blob->pbData);
1728 if (blob->cbData)
1730 BYTE mask = 0xff << blob->cUnusedBits;
1732 memcpy(blob->pbData, pbEncoded + 2 +
1733 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
1734 blob->pbData[blob->cbData - 1] &= mask;
1740 else
1742 SetLastError(CRYPT_E_ASN1_BADTAG);
1743 ret = FALSE;
1745 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1746 return ret;
1749 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType,
1750 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1751 void *pvStructInfo, DWORD *pcbStructInfo)
1753 BOOL ret = FALSE;
1754 DWORD dataLen;
1756 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1758 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1759 DWORD size;
1760 SPC_LINK **pLink = pvStructInfo;
1762 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType, lpszStructType,
1763 pbEncoded + 1 + lenBytes, dataLen, dwFlags, NULL, &size);
1764 if (ret)
1766 if (!pvStructInfo)
1767 *pcbStructInfo = size + sizeof(PSPC_LINK);
1768 else if (*pcbStructInfo < size + sizeof(PSPC_LINK))
1770 *pcbStructInfo = size + sizeof(PSPC_LINK);
1771 SetLastError(ERROR_MORE_DATA);
1772 ret = FALSE;
1774 else
1776 *pcbStructInfo = size + sizeof(PSPC_LINK);
1777 /* Set imageData's pointer if necessary */
1778 if (size > sizeof(SPC_LINK))
1780 (*pLink)->pwszUrl =
1781 (LPWSTR)((BYTE *)*pLink + sizeof(SPC_LINK));
1783 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1784 lpszStructType, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
1785 *pLink, pcbStructInfo);
1789 return ret;
1792 BOOL WINAPI WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType,
1793 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1794 void *pvStructInfo, DWORD *pcbStructInfo)
1796 BOOL ret = FALSE;
1798 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1799 pvStructInfo, *pcbStructInfo);
1801 __TRY
1803 struct AsnDecodeSequenceItem items[] = {
1804 { ASN_BITSTRING, offsetof(SPC_PE_IMAGE_DATA, Flags),
1805 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1806 offsetof(SPC_PE_IMAGE_DATA, Flags.pbData), 0 },
1807 { ASN_CONSTRUCTOR | ASN_CONTEXT, offsetof(SPC_PE_IMAGE_DATA, pFile),
1808 CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE,
1809 offsetof(SPC_PE_IMAGE_DATA, pFile), 0 },
1812 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
1813 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, NULL);
1815 __EXCEPT_PAGE_FAULT
1817 SetLastError(STATUS_ACCESS_VIOLATION);
1819 __ENDTRY
1820 TRACE("returning %d\n", ret);
1821 return ret;
1824 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType,
1825 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1826 void *pvStructInfo, DWORD *pcbStructInfo)
1828 BOOL ret = TRUE;
1829 DWORD dataLen;
1831 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1832 pvStructInfo, *pcbStructInfo);
1834 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1836 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1837 DWORD bytesNeeded = sizeof(LPSTR);
1839 if (dataLen)
1841 /* The largest possible string for the first two components
1842 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1844 char firstTwo[8];
1845 const BYTE *ptr;
1847 sprintf(firstTwo, "%d.%d",
1848 pbEncoded[1 + lenBytes] / 40,
1849 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1850 * 40);
1851 bytesNeeded += strlen(firstTwo) + 1;
1852 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1853 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1855 /* large enough for ".4000000" */
1856 char str[9];
1857 int val = 0;
1859 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1860 (*ptr & 0x80))
1862 val <<= 7;
1863 val |= *ptr & 0x7f;
1864 ptr++;
1866 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1867 (*ptr & 0x80))
1869 SetLastError(CRYPT_E_ASN1_CORRUPT);
1870 ret = FALSE;
1872 else
1874 val <<= 7;
1875 val |= *ptr++;
1876 snprintf(str, sizeof(str), ".%d", val);
1877 bytesNeeded += strlen(str);
1881 else
1882 bytesNeeded += 1;
1883 if (!pvStructInfo)
1884 *pcbStructInfo = bytesNeeded;
1885 else if (*pcbStructInfo < bytesNeeded)
1887 *pcbStructInfo = bytesNeeded;
1888 SetLastError(ERROR_MORE_DATA);
1889 ret = FALSE;
1891 else
1893 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1895 *pszObjId = 0;
1896 if (dataLen)
1898 const BYTE *ptr;
1900 pszObjId += sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1901 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1902 40) * 40);
1903 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1904 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1906 int val = 0;
1908 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1909 (*ptr & 0x80))
1911 val <<= 7;
1912 val |= *ptr & 0x7f;
1913 ptr++;
1915 val <<= 7;
1916 val |= *ptr++;
1917 pszObjId += sprintf(pszObjId, ".%d", val);
1920 *pcbStructInfo = bytesNeeded;
1923 return ret;
1926 static BOOL WINAPI CRYPT_AsnDecodeOid(DWORD dwCertEncodingType,
1927 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1928 void *pvStructInfo, DWORD *pcbStructInfo)
1930 BOOL ret = FALSE;
1932 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1933 pvStructInfo, *pcbStructInfo);
1935 if (!cbEncoded)
1936 SetLastError(CRYPT_E_ASN1_CORRUPT);
1937 else if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1938 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, lpszStructType,
1939 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
1940 else
1941 SetLastError(CRYPT_E_ASN1_BADTAG);
1942 return ret;
1945 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1946 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1947 void *pvStructInfo, DWORD *pcbStructInfo)
1949 BOOL ret = TRUE;
1950 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1952 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1953 pvStructInfo, *pcbStructInfo);
1955 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1956 bytesNeeded += cbEncoded;
1957 if (!pvStructInfo)
1958 *pcbStructInfo = bytesNeeded;
1959 else if (*pcbStructInfo < bytesNeeded)
1961 SetLastError(ERROR_MORE_DATA);
1962 *pcbStructInfo = bytesNeeded;
1963 ret = FALSE;
1965 else
1967 PCRYPT_OBJID_BLOB blob = pvStructInfo;
1969 *pcbStructInfo = bytesNeeded;
1970 blob->cbData = cbEncoded;
1971 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1972 blob->pbData = (LPBYTE)pbEncoded;
1973 else
1975 assert(blob->pbData);
1976 memcpy(blob->pbData, pbEncoded, blob->cbData);
1979 return ret;
1982 static BOOL WINAPI CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType,
1983 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1984 void *pvStructInfo, DWORD *pcbStructInfo)
1986 CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue = pvStructInfo;
1987 struct AsnDecodeSequenceItem items[] = {
1988 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId),
1989 CRYPT_AsnDecodeOid, sizeof(LPSTR), FALSE, TRUE,
1990 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId), 0 },
1991 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value),
1992 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
1993 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value.pbData), 0 },
1996 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1997 pvStructInfo, *pcbStructInfo);
1999 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2000 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo,
2001 typeValue ? typeValue->pszObjId : NULL);
2004 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
2005 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2006 void *pvStructInfo, DWORD *pcbStructInfo)
2008 CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
2009 BOOL ret = TRUE;
2010 struct AsnDecodeSequenceItem items[] = {
2011 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2012 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2013 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2014 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2015 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2016 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2019 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2020 pvStructInfo, *pcbStructInfo);
2022 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2023 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
2024 if (ret && pvStructInfo)
2026 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2027 debugstr_a(algo->pszObjId));
2029 return ret;
2032 static BOOL WINAPI CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType,
2033 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2034 void *pvStructInfo, DWORD *pcbStructInfo)
2036 struct SPCDigest *digest = pvStructInfo;
2037 struct AsnDecodeSequenceItem items[] = {
2038 { ASN_SEQUENCEOF, offsetof(struct SPCDigest, DigestAlgorithm),
2039 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2040 FALSE, TRUE,
2041 offsetof(struct SPCDigest, DigestAlgorithm.pszObjId), 0 },
2042 { ASN_OCTETSTRING, offsetof(struct SPCDigest, Digest),
2043 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
2044 FALSE, TRUE, offsetof(struct SPCDigest, Digest.pbData), 0 },
2047 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2048 pvStructInfo, *pcbStructInfo);
2050 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2051 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo,
2052 digest ? digest->DigestAlgorithm.pszObjId : NULL);
2055 BOOL WINAPI WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType,
2056 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2057 void *pvStructInfo, DWORD *pcbStructInfo)
2059 BOOL ret = FALSE;
2061 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2062 pvStructInfo, *pcbStructInfo);
2064 __TRY
2066 struct AsnDecodeSequenceItem items[] = {
2067 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, Data),
2068 CRYPT_AsnDecodeAttributeTypeValue,
2069 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE), FALSE, TRUE,
2070 offsetof(SPC_INDIRECT_DATA_CONTENT, Data.pszObjId), 0 },
2071 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm),
2072 CRYPT_AsnDecodeSPCDigest, sizeof(struct SPCDigest),
2073 FALSE, TRUE,
2074 offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm.pszObjId), 0 },
2077 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2078 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2080 __EXCEPT_PAGE_FAULT
2082 SetLastError(STATUS_ACCESS_VIOLATION);
2084 __ENDTRY
2085 TRACE("returning %d\n", ret);
2086 return ret;
2089 static BOOL WINAPI CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType,
2090 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2091 void *pvStructInfo, DWORD *pcbStructInfo)
2093 BOOL ret;
2094 DWORD bytesNeeded, dataLen;
2096 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2098 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2100 bytesNeeded = dataLen + 2 + sizeof(LPWSTR);
2101 if (!pvStructInfo)
2102 *pcbStructInfo = bytesNeeded;
2103 else if (*pcbStructInfo < bytesNeeded)
2105 *pcbStructInfo = bytesNeeded;
2106 SetLastError(ERROR_MORE_DATA);
2107 ret = FALSE;
2109 else
2111 LPWSTR str;
2112 DWORD i;
2114 *pcbStructInfo = bytesNeeded;
2115 assert(pvStructInfo);
2116 str = *(LPWSTR *)pvStructInfo;
2117 for (i = 0; i < dataLen / 2; i++)
2118 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2119 pbEncoded[1 + lenBytes + 2 * i + 1];
2120 /* Decoded string is always NULL-terminated */
2121 str[i] = '\0';
2124 return ret;
2127 static BOOL WINAPI CRYPT_AsnDecodeProgramName(DWORD dwCertEncodingType,
2128 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2129 void *pvStructInfo, DWORD *pcbStructInfo)
2131 BOOL ret = FALSE;
2132 DWORD dataLen;
2134 TRACE("(%p, %ld, %08lx, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2135 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2137 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2139 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2141 ret = CRYPT_AsnDecodeBMPString(dwCertEncodingType, lpszStructType,
2142 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pvStructInfo,
2143 pcbStructInfo);
2145 return ret;
2148 BOOL WINAPI WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType,
2149 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2150 void *pvStructInfo, DWORD *pcbStructInfo)
2152 BOOL ret = FALSE;
2154 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2155 pvStructInfo, *pcbStructInfo);
2157 __TRY
2159 struct AsnDecodeSequenceItem items[] = {
2160 { ASN_CONSTRUCTOR | ASN_CONTEXT,
2161 offsetof(SPC_SP_OPUS_INFO, pwszProgramName),
2162 CRYPT_AsnDecodeProgramName, sizeof(LPCWSTR), TRUE, TRUE,
2163 offsetof(SPC_SP_OPUS_INFO, pwszProgramName), 0 },
2164 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
2165 offsetof(SPC_SP_OPUS_INFO, pMoreInfo),
2166 CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE,
2167 offsetof(SPC_SP_OPUS_INFO, pMoreInfo), 0 },
2168 { ASN_CONSTRUCTOR | ASN_CONTEXT | 2,
2169 offsetof(SPC_SP_OPUS_INFO, pPublisherInfo),
2170 CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE,
2171 offsetof(SPC_SP_OPUS_INFO, pPublisherInfo), 0 },
2174 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2175 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2177 __EXCEPT_PAGE_FAULT
2179 SetLastError(STATUS_ACCESS_VIOLATION);
2181 __ENDTRY
2182 TRACE("returning %d\n", ret);
2183 return ret;
2186 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
2187 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2188 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2189 void *pvStructInfo, DWORD *pcbStructInfo)
2191 BOOL ret;
2192 DWORD dataLen;
2194 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2196 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2198 if (dataLen > sizeof(int))
2200 SetLastError(CRYPT_E_ASN1_LARGE);
2201 ret = FALSE;
2203 else if (!pvStructInfo)
2204 *pcbStructInfo = sizeof(int);
2205 else if (*pcbStructInfo < sizeof(int))
2207 *pcbStructInfo = sizeof(int);
2208 SetLastError(ERROR_MORE_DATA);
2209 ret = FALSE;
2211 else
2213 int val;
2214 DWORD i;
2216 *pcbStructInfo = sizeof(int);
2217 if (dataLen && pbEncoded[1 + lenBytes] & 0x80)
2219 /* initialize to a negative value to sign-extend */
2220 val = -1;
2222 else
2223 val = 0;
2224 for (i = 0; i < dataLen; i++)
2226 val <<= 8;
2227 val |= pbEncoded[1 + lenBytes + i];
2229 memcpy(pvStructInfo, &val, sizeof(int));
2232 return ret;
2235 BOOL WINAPI WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType,
2236 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2237 void *pvStructInfo, DWORD *pcbStructInfo)
2239 BOOL ret = FALSE;
2241 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2242 pvStructInfo, *pcbStructInfo);
2244 __TRY
2246 struct AsnDecodeSequenceItem items[] = {
2247 { ASN_BMPSTRING, offsetof(CAT_MEMBERINFO, pwszSubjGuid),
2248 CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
2249 offsetof(CAT_MEMBERINFO, pwszSubjGuid), 0 },
2250 { ASN_INTEGER, offsetof(CAT_MEMBERINFO, dwCertVersion),
2251 CRYPT_AsnDecodeInt, FINALMEMBERSIZE(CAT_MEMBERINFO, dwCertVersion),
2252 FALSE, FALSE, 0, 0 },
2255 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2256 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2258 __EXCEPT_PAGE_FAULT
2260 SetLastError(STATUS_ACCESS_VIOLATION);
2262 __ENDTRY
2263 TRACE("returning %d\n", ret);
2264 return ret;
2267 BOOL WINAPI WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType,
2268 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2269 void *pvStructInfo, DWORD *pcbStructInfo)
2271 BOOL ret = FALSE;
2273 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2274 pvStructInfo, *pcbStructInfo);
2276 __TRY
2278 struct AsnDecodeSequenceItem items[] = {
2279 { ASN_BMPSTRING, offsetof(CAT_NAMEVALUE, pwszTag),
2280 CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
2281 offsetof(CAT_NAMEVALUE, pwszTag), 0 },
2282 { ASN_INTEGER, offsetof(CAT_NAMEVALUE, fdwFlags),
2283 CRYPT_AsnDecodeInt, MEMBERSIZE(CAT_NAMEVALUE, fdwFlags, Value),
2284 FALSE, FALSE, 0, 0 },
2285 { ASN_OCTETSTRING, offsetof(CAT_NAMEVALUE, Value),
2286 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
2287 offsetof(CAT_NAMEVALUE, Value.pbData), 0 },
2290 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2291 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2293 __EXCEPT_PAGE_FAULT
2295 SetLastError(STATUS_ACCESS_VIOLATION);
2297 __ENDTRY
2298 TRACE("returning %d\n", ret);
2299 return ret;
2302 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2303 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2304 void *pvStructInfo, DWORD *pcbStructInfo)
2306 BOOL ret;
2308 if (cbEncoded < 3)
2310 SetLastError(CRYPT_E_ASN1_CORRUPT);
2311 return FALSE;
2313 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2315 SetLastError(CRYPT_E_ASN1_CORRUPT);
2316 return FALSE;
2318 if (pbEncoded[1] > 1)
2320 SetLastError(CRYPT_E_ASN1_CORRUPT);
2321 return FALSE;
2323 if (!pvStructInfo)
2325 *pcbStructInfo = sizeof(BOOL);
2326 ret = TRUE;
2328 else if (*pcbStructInfo < sizeof(BOOL))
2330 *pcbStructInfo = sizeof(BOOL);
2331 SetLastError(ERROR_MORE_DATA);
2332 ret = FALSE;
2334 else
2336 *pcbStructInfo = sizeof(BOOL);
2337 *(BOOL *)pvStructInfo = pbEncoded[2] != 0;
2338 ret = TRUE;
2340 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2341 return ret;
2344 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoDecode(DWORD dwCertEncodingType,
2345 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2346 void *pvStructInfo, DWORD *pcbStructInfo)
2348 BOOL ret = FALSE;
2350 TRACE("(%p, %ld, %08lx, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2351 pvStructInfo, *pcbStructInfo);
2353 __TRY
2355 struct AsnDecodeSequenceItem items[] = {
2356 { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fFinancialInfoAvailable),
2357 CRYPT_AsnDecodeBool, MEMBERSIZE(SPC_FINANCIAL_CRITERIA,
2358 fFinancialInfoAvailable, fMeetsCriteria), FALSE, FALSE, 0, 0 },
2359 { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fMeetsCriteria),
2360 CRYPT_AsnDecodeBool, FINALMEMBERSIZE(SPC_FINANCIAL_CRITERIA,
2361 fMeetsCriteria), FALSE, FALSE, 0, 0 },
2364 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, ARRAY_SIZE(items),
2365 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2367 __EXCEPT_PAGE_FAULT
2369 SetLastError(STATUS_ACCESS_VIOLATION);
2371 __ENDTRY
2372 TRACE("returning %d\n", ret);
2373 return ret;