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
22 #include "wine/port.h"
27 #define NONAMELESSUNION
35 #include "wine/debug.h"
36 #include "wine/exception.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
40 #ifdef WORDS_BIGENDIAN
47 #define hton16(x) RtlUshortByteSwap(x)
48 #define n16toh(x) RtlUshortByteSwap(x)
52 #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
53 #define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
54 #define ASN_BMPSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1e)
56 static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
58 DWORD bytesNeeded, significantBytes = 0;
66 for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
67 temp <<= 8, significantBytes--)
69 bytesNeeded = significantBytes + 1;
73 *pcbEncoded = bytesNeeded;
76 if (*pcbEncoded < bytesNeeded)
78 SetLastError(ERROR_MORE_DATA);
82 *pbEncoded = (BYTE)len;
87 *pbEncoded++ = significantBytes | 0x80;
88 for (i = 0; i < significantBytes; i++)
90 *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
94 *pcbEncoded = bytesNeeded;
98 static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
99 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
103 const CRYPT_DATA_BLOB *blob = pvStructInfo;
104 DWORD bytesNeeded, lenBytes;
106 TRACE("(%d, %p), %p, %d\n", blob->cbData, blob->pbData, pbEncoded,
109 CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
110 bytesNeeded = 1 + lenBytes + blob->cbData;
112 *pcbEncoded = bytesNeeded;
113 else if (*pcbEncoded < bytesNeeded)
115 *pcbEncoded = bytesNeeded;
116 SetLastError(ERROR_MORE_DATA);
121 *pbEncoded++ = ASN_OCTETSTRING;
122 CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
123 pbEncoded += lenBytes;
125 memcpy(pbEncoded, blob->pbData, blob->cbData);
127 TRACE("returning %d\n", ret);
131 BOOL WINAPI WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType,
132 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
137 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
138 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
143 const SPC_LINK *link = pvStructInfo;
144 DWORD bytesNeeded, lenBytes;
146 switch (link->dwLinkChoice)
148 case SPC_FILE_LINK_CHOICE:
150 DWORD fileNameLen, fileNameLenBytes;
153 fileNameLen = link->u.pwszFile ?
154 lstrlenW(link->u.pwszFile) * sizeof(WCHAR) : 0;
155 CRYPT_EncodeLen(fileNameLen, NULL, &fileNameLenBytes);
156 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, NULL,
158 bytesNeeded = 2 + lenBytes + fileNameLenBytes + fileNameLen;
161 *pcbEncoded = bytesNeeded;
164 else if (*pcbEncoded < bytesNeeded)
166 SetLastError(ERROR_MORE_DATA);
167 *pcbEncoded = bytesNeeded;
171 *pcbEncoded = bytesNeeded;
172 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 2;
173 CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, pbEncoded,
175 pbEncoded += lenBytes;
176 *pbEncoded++ = ASN_CONTEXT;
177 CRYPT_EncodeLen(fileNameLen, pbEncoded, &fileNameLenBytes);
178 pbEncoded += fileNameLenBytes;
179 for (ptr = link->u.pwszFile; ptr && *ptr; ptr++)
181 *(WCHAR *)pbEncoded = hton16(*ptr);
182 pbEncoded += sizeof(WCHAR);
188 case SPC_MONIKER_LINK_CHOICE:
190 DWORD classIdLenBytes, dataLenBytes, dataLen;
191 CRYPT_DATA_BLOB classId = { sizeof(link->u.Moniker.ClassId),
192 (BYTE *)link->u.Moniker.ClassId };
194 CRYPT_EncodeLen(classId.cbData, NULL, &classIdLenBytes);
195 CRYPT_EncodeLen(link->u.Moniker.SerializedData.cbData, NULL,
197 dataLen = 2 + classIdLenBytes + classId.cbData +
198 dataLenBytes + link->u.Moniker.SerializedData.cbData;
199 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
200 bytesNeeded = 1 + dataLen + lenBytes;
203 *pcbEncoded = bytesNeeded;
206 else if (*pcbEncoded < bytesNeeded)
208 SetLastError(ERROR_MORE_DATA);
209 *pcbEncoded = bytesNeeded;
215 *pcbEncoded = bytesNeeded;
216 *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
217 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
218 pbEncoded += lenBytes;
219 size = 1 + classIdLenBytes + classId.cbData;
220 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL, &classId,
223 size = 1 + dataLenBytes + link->u.Moniker.SerializedData.cbData;
224 CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL,
225 &link->u.Moniker.SerializedData, pbEncoded, &size);
231 case SPC_URL_LINK_CHOICE:
236 /* Check for invalid characters in URL */
239 for (ptr = link->u.pwszUrl; ptr && *ptr && ret; ptr++)
243 SetLastError(CRYPT_E_INVALID_IA5_STRING);
250 CRYPT_EncodeLen(urlLen, NULL, &lenBytes);
251 bytesNeeded = 1 + lenBytes + urlLen;
253 *pcbEncoded = bytesNeeded;
254 else if (*pcbEncoded < bytesNeeded)
256 SetLastError(ERROR_MORE_DATA);
257 *pcbEncoded = bytesNeeded;
262 *pcbEncoded = bytesNeeded;
263 *pbEncoded++ = ASN_CONTEXT;
264 CRYPT_EncodeLen(urlLen, pbEncoded, &lenBytes);
265 pbEncoded += lenBytes;
266 for (ptr = link->u.pwszUrl; ptr && *ptr; ptr++)
267 *pbEncoded++ = (BYTE)*ptr;
273 SetLastError(E_INVALIDARG);
278 SetLastError(STATUS_ACCESS_VIOLATION);
281 TRACE("returning %d\n", ret);
285 typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
288 struct AsnEncodeSequenceItem
290 const void *pvStructInfo;
291 CryptEncodeObjectFunc encodeFunc;
292 DWORD size; /* used during encoding, not for your use */
295 static BOOL CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
296 struct AsnEncodeSequenceItem items[], DWORD cItem, BYTE *pbEncoded,
300 DWORD i, dataLen = 0;
302 TRACE("%p, %d, %p, %d\n", items, cItem, pbEncoded, *pcbEncoded);
303 for (i = 0, ret = TRUE; ret && i < cItem; i++)
305 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
306 items[i].pvStructInfo, NULL, &items[i].size);
307 /* Some functions propagate their errors through the size */
309 *pcbEncoded = items[i].size;
310 dataLen += items[i].size;
314 DWORD lenBytes, bytesNeeded;
316 CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
317 bytesNeeded = 1 + lenBytes + dataLen;
319 *pcbEncoded = bytesNeeded;
320 else if (*pcbEncoded < bytesNeeded)
322 *pcbEncoded = bytesNeeded;
323 SetLastError(ERROR_MORE_DATA);
328 *pcbEncoded = bytesNeeded;
329 *pbEncoded++ = ASN_SEQUENCE;
330 CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
331 pbEncoded += lenBytes;
332 for (i = 0; ret && i < cItem; i++)
334 ret = items[i].encodeFunc(dwCertEncodingType, NULL,
335 items[i].pvStructInfo, pbEncoded, &items[i].size);
336 /* Some functions propagate their errors through the size */
338 *pcbEncoded = items[i].size;
339 pbEncoded += items[i].size;
343 TRACE("returning %d\n", ret);
347 static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
348 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
355 const CRYPT_BIT_BLOB *blob = pvStructInfo;
356 DWORD bytesNeeded, lenBytes, dataBytes;
359 /* yep, MS allows cUnusedBits to be >= 8 */
360 if (!blob->cUnusedBits)
362 dataBytes = blob->cbData;
365 else if (blob->cbData * 8 > blob->cUnusedBits)
367 dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
368 unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
376 CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
377 bytesNeeded = 1 + lenBytes + dataBytes + 1;
380 *pcbEncoded = bytesNeeded;
383 else if (*pcbEncoded < bytesNeeded)
385 *pcbEncoded = bytesNeeded;
386 SetLastError(ERROR_MORE_DATA);
391 *pcbEncoded = bytesNeeded;
392 *pbEncoded++ = ASN_BITSTRING;
393 CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
394 pbEncoded += lenBytes;
395 *pbEncoded++ = unusedBits;
398 BYTE mask = 0xff << unusedBits;
402 memcpy(pbEncoded, blob->pbData, dataBytes - 1);
403 pbEncoded += dataBytes - 1;
405 *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
411 SetLastError(STATUS_ACCESS_VIOLATION);
417 struct AsnConstructedItem
420 const void *pvStructInfo;
421 CryptEncodeObjectFunc encodeFunc;
424 static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
425 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
429 const struct AsnConstructedItem *item = pvStructInfo;
432 if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
433 item->pvStructInfo, NULL, &len)))
435 DWORD dataLen, bytesNeeded;
437 CRYPT_EncodeLen(len, NULL, &dataLen);
438 bytesNeeded = 1 + dataLen + len;
440 *pcbEncoded = bytesNeeded;
441 else if (*pcbEncoded < bytesNeeded)
443 *pcbEncoded = bytesNeeded;
444 SetLastError(ERROR_MORE_DATA);
449 *pcbEncoded = bytesNeeded;
450 *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
451 CRYPT_EncodeLen(len, pbEncoded, &dataLen);
452 pbEncoded += dataLen;
453 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
454 item->pvStructInfo, pbEncoded, &len);
457 /* Some functions propagate their errors through the size */
464 /* Some functions propagate their errors through the size */
471 BOOL WINAPI WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType,
472 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
475 const SPC_PE_IMAGE_DATA *imageData = pvStructInfo;
478 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
479 debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
484 struct AsnEncodeSequenceItem items[2] = {
487 struct AsnConstructedItem constructed = { 0, imageData->pFile,
488 WVTAsn1SpcLinkEncode };
491 if (imageData->Flags.cbData)
493 items[cItem].pvStructInfo = &imageData->Flags;
494 items[cItem].encodeFunc = CRYPT_AsnEncodeBits;
497 if (imageData->pFile)
499 items[cItem].pvStructInfo = &constructed;
500 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
504 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
505 pbEncoded, pcbEncoded);
509 SetLastError(STATUS_ACCESS_VIOLATION);
512 TRACE("returning %d\n", ret);
516 static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
517 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
520 LPCSTR pszObjId = pvStructInfo;
521 DWORD bytesNeeded = 0, lenBytes;
526 TRACE("%s\n", debugstr_a(pszObjId));
533 if (sscanf(pszObjId, "%d.%d%n", &val1, &val2, &firstPos) != 2)
535 SetLastError(CRYPT_E_ASN1_ERROR);
539 firstByte = val1 * 40 + val2;
540 ptr = pszObjId + firstPos;
550 /* note I assume each component is at most 32-bits long in base 2 */
551 if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
553 if (val1 >= 0x10000000)
555 else if (val1 >= 0x200000)
557 else if (val1 >= 0x4000)
559 else if (val1 >= 0x80)
569 SetLastError(CRYPT_E_ASN1_ERROR);
573 CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
577 bytesNeeded += 1 + lenBytes;
580 if (*pcbEncoded < bytesNeeded)
582 SetLastError(ERROR_MORE_DATA);
587 *pbEncoded++ = ASN_OBJECTIDENTIFIER;
588 CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
589 pbEncoded += lenBytes;
595 *pbEncoded++ = firstByte;
596 ptr = pszObjId + firstPos;
599 sscanf(ptr, "%d%n", &val, &pos);
601 unsigned char outBytes[5];
604 if (val >= 0x10000000)
606 else if (val >= 0x200000)
608 else if (val >= 0x4000)
610 else if (val >= 0x80)
614 for (i = numBytes; i > 0; i--)
616 outBytes[i - 1] = val & 0x7f;
619 for (i = 0; i < numBytes - 1; i++)
620 *pbEncoded++ = outBytes[i] | 0x80;
621 *pbEncoded++ = outBytes[i];
630 *pcbEncoded = bytesNeeded;
634 static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
635 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
638 const CRYPT_DER_BLOB *blob = pvStructInfo;
642 *pcbEncoded = blob->cbData;
643 else if (*pcbEncoded < blob->cbData)
645 *pcbEncoded = blob->cbData;
646 SetLastError(ERROR_MORE_DATA);
652 memcpy(pbEncoded, blob->pbData, blob->cbData);
653 *pcbEncoded = blob->cbData;
658 static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
659 DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
660 BYTE *pbEncoded, DWORD *pcbEncoded)
662 const CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
663 static const BYTE asn1Null[] = { ASN_NULL, 0 };
664 static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
667 struct AsnEncodeSequenceItem items[2] = {
668 { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
669 { NULL, CRYPT_CopyEncodedBlob, 0 },
672 if (algo->Parameters.cbData)
673 items[1].pvStructInfo = &algo->Parameters;
675 items[1].pvStructInfo = &nullBlob;
676 ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
677 sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
681 static BOOL WINAPI CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType,
682 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
685 const CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue = pvStructInfo;
686 struct AsnEncodeSequenceItem items[] = {
687 { &typeValue->pszObjId, CRYPT_AsnEncodeOid, 0 },
688 { &typeValue->Value, CRYPT_CopyEncodedBlob, 0 },
691 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
692 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
697 CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm;
698 CRYPT_HASH_BLOB Digest;
701 static BOOL WINAPI CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType,
702 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
705 const struct SPCDigest *digest = pvStructInfo;
706 struct AsnEncodeSequenceItem items[] = {
707 { &digest->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
708 { &digest->Digest, CRYPT_CopyEncodedBlob, 0 },
711 return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
712 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
715 BOOL WINAPI WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType,
716 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
721 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
722 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
726 const SPC_INDIRECT_DATA_CONTENT *data = pvStructInfo;
727 struct AsnEncodeSequenceItem items[] = {
728 { &data->Data, CRYPT_AsnEncodeAttributeTypeValue, 0 },
729 { &data->DigestAlgorithm, CRYPT_AsnEncodeSPCDigest, 0 },
732 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
733 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
737 SetLastError(STATUS_ACCESS_VIOLATION);
743 static BOOL WINAPI CRYPT_AsnEncodeBMPString(DWORD dwCertEncodingType,
744 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
748 LPCWSTR str = pvStructInfo;
749 DWORD bytesNeeded, lenBytes, strLen;
752 strLen = lstrlenW(str);
755 CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
756 bytesNeeded = 1 + lenBytes + strLen * 2;
758 *pcbEncoded = bytesNeeded;
759 else if (*pcbEncoded < bytesNeeded)
761 *pcbEncoded = bytesNeeded;
762 SetLastError(ERROR_MORE_DATA);
769 *pcbEncoded = bytesNeeded;
770 *pbEncoded++ = ASN_BMPSTRING;
771 CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
772 pbEncoded += lenBytes;
773 for (i = 0; i < strLen; i++)
775 *pbEncoded++ = (str[i] & 0xff00) >> 8;
776 *pbEncoded++ = str[i] & 0x00ff;
782 struct AsnEncodeTagSwappedItem
785 const void *pvStructInfo;
786 CryptEncodeObjectFunc encodeFunc;
789 /* Sort of a wacky hack, it encodes something using the struct
790 * AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
791 * given in the struct AsnEncodeTagSwappedItem.
793 static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
794 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
798 const struct AsnEncodeTagSwappedItem *item = pvStructInfo;
800 ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
801 item->pvStructInfo, pbEncoded, pcbEncoded);
802 if (ret && pbEncoded)
803 *pbEncoded = item->tag;
807 BOOL WINAPI WVTAsn1SpcSpOpusInfoEncode(DWORD dwCertEncodingType,
808 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
813 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
814 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
818 const SPC_SP_OPUS_INFO *info = pvStructInfo;
820 if (info->pMoreInfo &&
821 info->pMoreInfo->dwLinkChoice != SPC_URL_LINK_CHOICE &&
822 info->pMoreInfo->dwLinkChoice != SPC_MONIKER_LINK_CHOICE &&
823 info->pMoreInfo->dwLinkChoice != SPC_FILE_LINK_CHOICE)
824 SetLastError(E_INVALIDARG);
825 else if (info->pPublisherInfo &&
826 info->pPublisherInfo->dwLinkChoice != SPC_URL_LINK_CHOICE &&
827 info->pPublisherInfo->dwLinkChoice != SPC_MONIKER_LINK_CHOICE &&
828 info->pPublisherInfo->dwLinkChoice != SPC_FILE_LINK_CHOICE)
829 SetLastError(E_INVALIDARG);
832 struct AsnEncodeSequenceItem items[3] = { { 0 } };
833 struct AsnConstructedItem constructed[3] = { { 0 } };
834 struct AsnEncodeTagSwappedItem swapped;
835 DWORD cItem = 0, cConstructed = 0;
837 if (info->pwszProgramName)
839 swapped.tag = ASN_CONTEXT;
840 swapped.pvStructInfo = info->pwszProgramName;
841 swapped.encodeFunc = CRYPT_AsnEncodeBMPString;
842 constructed[cConstructed].tag = 0;
843 constructed[cConstructed].pvStructInfo = &swapped;
844 constructed[cConstructed].encodeFunc = CRYPT_AsnEncodeSwapTag;
845 items[cItem].pvStructInfo = &constructed[cConstructed];
846 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
852 constructed[cConstructed].tag = 1;
853 constructed[cConstructed].pvStructInfo = info->pMoreInfo;
854 constructed[cConstructed].encodeFunc = WVTAsn1SpcLinkEncode;
855 items[cItem].pvStructInfo = &constructed[cConstructed];
856 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
860 if (info->pPublisherInfo)
862 constructed[cConstructed].tag = 2;
863 constructed[cConstructed].pvStructInfo = info->pPublisherInfo;
864 constructed[cConstructed].encodeFunc = WVTAsn1SpcLinkEncode;
865 items[cItem].pvStructInfo = &constructed[cConstructed];
866 items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
870 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
871 items, cItem, pbEncoded, pcbEncoded);
876 SetLastError(STATUS_ACCESS_VIOLATION);
882 static BOOL CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
883 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
890 DWORD significantBytes, lenBytes, bytesNeeded;
893 const CRYPT_INTEGER_BLOB *blob = pvStructInfo;
895 significantBytes = blob->cbData;
896 if (significantBytes)
898 if (blob->pbData[significantBytes - 1] & 0x80)
900 /* negative, lop off leading (little-endian) 0xffs */
901 for (; significantBytes > 0 &&
902 blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
904 if (blob->pbData[significantBytes - 1] < 0x80)
912 /* positive, lop off leading (little-endian) zeroes */
913 for (; significantBytes > 0 &&
914 !blob->pbData[significantBytes - 1]; significantBytes--)
916 if (significantBytes == 0)
917 significantBytes = 1;
918 if (blob->pbData[significantBytes - 1] > 0x7f)
926 CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
928 CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
929 bytesNeeded = 1 + lenBytes + significantBytes;
934 *pcbEncoded = bytesNeeded;
937 else if (*pcbEncoded < bytesNeeded)
939 *pcbEncoded = bytesNeeded;
940 SetLastError(ERROR_MORE_DATA);
945 *pcbEncoded = bytesNeeded;
946 *pbEncoded++ = ASN_INTEGER;
949 CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
950 pbEncoded += lenBytes;
951 *pbEncoded++ = padByte;
955 CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
956 pbEncoded += lenBytes;
958 for (; significantBytes > 0; significantBytes--)
959 *(pbEncoded++) = blob->pbData[significantBytes - 1];
965 SetLastError(STATUS_ACCESS_VIOLATION);
972 static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
973 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
976 CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
978 return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
979 &blob, pbEncoded, pcbEncoded);
982 BOOL WINAPI WVTAsn1CatMemberInfoEncode(DWORD dwCertEncodingType,
983 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
988 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
989 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
993 const CAT_MEMBERINFO *info = pvStructInfo;
994 struct AsnEncodeSequenceItem items[] = {
995 { info->pwszSubjGuid, CRYPT_AsnEncodeBMPString, 0 },
996 { &info->dwCertVersion, CRYPT_AsnEncodeInt, 0 },
999 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
1000 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
1004 SetLastError(STATUS_ACCESS_VIOLATION);
1010 BOOL WINAPI WVTAsn1CatNameValueEncode(DWORD dwCertEncodingType,
1011 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
1016 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
1017 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
1021 const CAT_NAMEVALUE *value = pvStructInfo;
1022 struct AsnEncodeSequenceItem items[] = {
1023 { value->pwszTag, CRYPT_AsnEncodeBMPString, 0 },
1024 { &value->fdwFlags, CRYPT_AsnEncodeInt, 0 },
1025 { &value->Value, CRYPT_AsnEncodeOctets, 0 },
1028 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
1029 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
1033 SetLastError(STATUS_ACCESS_VIOLATION);
1039 static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
1040 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
1043 BOOL val = *(const BOOL *)pvStructInfo, ret;
1052 else if (*pcbEncoded < 3)
1055 SetLastError(ERROR_MORE_DATA);
1061 *pbEncoded++ = ASN_BOOL;
1063 *pbEncoded++ = val ? 0xff : 0;
1066 TRACE("returning %d (%08x)\n", ret, GetLastError());
1070 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoEncode(DWORD dwCertEncodingType,
1071 LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
1076 TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
1077 debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
1081 const SPC_FINANCIAL_CRITERIA *criteria = pvStructInfo;
1082 struct AsnEncodeSequenceItem items[] = {
1083 { &criteria->fFinancialInfoAvailable, CRYPT_AsnEncodeBool, 0 },
1084 { &criteria->fMeetsCriteria, CRYPT_AsnEncodeBool, 0 },
1087 ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
1088 items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
1092 SetLastError(STATUS_ACCESS_VIOLATION);
1098 /* Gets the number of length bytes from the given (leading) length byte */
1099 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
1101 /* Helper function to get the encoded length of the data starting at pbEncoded,
1102 * where pbEncoded[0] is the tag. If the data are too short to contain a
1103 * length or if the length is too large for cbEncoded, sets an appropriate
1104 * error code and returns FALSE.
1106 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
1112 SetLastError(CRYPT_E_ASN1_CORRUPT);
1115 else if (pbEncoded[1] <= 0x7f)
1117 if (pbEncoded[1] + 1 > cbEncoded)
1119 SetLastError(CRYPT_E_ASN1_EOD);
1124 *len = pbEncoded[1];
1128 else if (pbEncoded[1] == 0x80)
1130 FIXME("unimplemented for indefinite-length encoding\n");
1131 SetLastError(CRYPT_E_ASN1_CORRUPT);
1136 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
1138 if (lenLen > sizeof(DWORD) + 1)
1140 SetLastError(CRYPT_E_ASN1_LARGE);
1143 else if (lenLen + 2 > cbEncoded)
1145 SetLastError(CRYPT_E_ASN1_CORRUPT);
1156 out |= *pbEncoded++;
1158 if (out + lenLen + 1 > cbEncoded)
1160 SetLastError(CRYPT_E_ASN1_EOD);
1173 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
1174 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1175 void *pvStructInfo, DWORD *pcbStructInfo)
1178 DWORD bytesNeeded, dataLen;
1180 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1181 pvStructInfo, *pcbStructInfo);
1185 SetLastError(CRYPT_E_ASN1_CORRUPT);
1188 else if (pbEncoded[0] != ASN_OCTETSTRING)
1190 SetLastError(CRYPT_E_ASN1_BADTAG);
1193 else if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1195 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1196 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
1198 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
1200 *pcbStructInfo = bytesNeeded;
1201 else if (*pcbStructInfo < bytesNeeded)
1203 SetLastError(ERROR_MORE_DATA);
1204 *pcbStructInfo = bytesNeeded;
1209 CRYPT_DATA_BLOB *blob;
1210 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1212 blob = pvStructInfo;
1213 blob->cbData = dataLen;
1214 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1215 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
1218 assert(blob->pbData);
1220 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
1228 static BOOL CRYPT_AsnDecodeSPCLinkInternal(DWORD dwCertEncodingType,
1229 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1230 void *pvStructInfo, DWORD *pcbStructInfo)
1233 DWORD bytesNeeded = sizeof(SPC_LINK), dataLen;
1235 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1236 pvStructInfo, *pcbStructInfo);
1238 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1240 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1243 switch (pbEncoded[0])
1246 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
1248 *pcbStructInfo = bytesNeeded;
1249 else if (*pcbStructInfo < bytesNeeded)
1251 *pcbStructInfo = bytesNeeded;
1252 SetLastError(ERROR_MORE_DATA);
1257 PSPC_LINK link = pvStructInfo;
1260 link->dwLinkChoice = SPC_URL_LINK_CHOICE;
1261 for (i = 0; i < dataLen; i++)
1262 link->u.pwszUrl[i] =
1263 *(pbEncoded + 1 + lenBytes + i);
1264 link->u.pwszUrl[i] = '\0';
1265 TRACE("returning url %s\n", debugstr_w(link->u.pwszUrl));
1268 case ASN_CONSTRUCTOR | ASN_CONTEXT | 1:
1270 CRYPT_DATA_BLOB classId;
1271 DWORD size = sizeof(classId);
1273 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
1274 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
1275 CRYPT_DECODE_NOCOPY_FLAG, &classId, &size)))
1277 if (classId.cbData != sizeof(SPC_UUID))
1279 SetLastError(CRYPT_E_BAD_ENCODE);
1284 CRYPT_DATA_BLOB data;
1286 /* The tag length for the classId must be 1 since the
1287 * length is correct.
1289 size = sizeof(data);
1290 if ((ret = CRYPT_AsnDecodeOctets(dwCertEncodingType, NULL,
1291 pbEncoded + 3 + lenBytes + classId.cbData,
1292 cbEncoded - 3 - lenBytes - classId.cbData,
1293 CRYPT_DECODE_NOCOPY_FLAG, &data, &size)))
1295 bytesNeeded += data.cbData;
1297 *pcbStructInfo = bytesNeeded;
1298 else if (*pcbStructInfo < bytesNeeded)
1300 *pcbStructInfo = bytesNeeded;
1301 SetLastError(ERROR_MORE_DATA);
1306 PSPC_LINK link = pvStructInfo;
1308 link->dwLinkChoice = SPC_MONIKER_LINK_CHOICE;
1309 /* pwszFile pointer was set by caller, copy it
1310 * before overwriting it
1312 link->u.Moniker.SerializedData.pbData =
1313 (BYTE *)link->u.pwszFile;
1314 memcpy(link->u.Moniker.ClassId, classId.pbData,
1316 memcpy(link->u.Moniker.SerializedData.pbData,
1317 data.pbData, data.cbData);
1318 link->u.Moniker.SerializedData.cbData = data.cbData;
1325 case ASN_CONSTRUCTOR | ASN_CONTEXT | 2:
1326 if (dataLen && pbEncoded[1 + lenBytes] != ASN_CONTEXT)
1327 SetLastError(CRYPT_E_ASN1_BADTAG);
1328 else if ((ret = CRYPT_GetLen(pbEncoded + 1 + lenBytes, dataLen,
1331 BYTE realLenBytes = GET_LEN_BYTES(pbEncoded[2 + lenBytes]);
1333 bytesNeeded += realDataLen + sizeof(WCHAR);
1335 *pcbStructInfo = bytesNeeded;
1336 else if (*pcbStructInfo < bytesNeeded)
1338 *pcbStructInfo = bytesNeeded;
1339 SetLastError(ERROR_MORE_DATA);
1344 PSPC_LINK link = pvStructInfo;
1346 const BYTE *ptr = pbEncoded + 2 + lenBytes + realLenBytes;
1348 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1349 for (i = 0; i < dataLen / sizeof(WCHAR); i++)
1350 link->u.pwszFile[i] =
1351 hton16(*(WORD *)(ptr + i * sizeof(WCHAR)));
1352 link->u.pwszFile[realDataLen / sizeof(WCHAR)] = '\0';
1353 TRACE("returning file %s\n", debugstr_w(link->u.pwszFile));
1358 bytesNeeded += sizeof(WCHAR);
1360 *pcbStructInfo = bytesNeeded;
1361 else if (*pcbStructInfo < bytesNeeded)
1363 *pcbStructInfo = bytesNeeded;
1364 SetLastError(ERROR_MORE_DATA);
1369 PSPC_LINK link = pvStructInfo;
1371 link->dwLinkChoice = SPC_FILE_LINK_CHOICE;
1372 link->u.pwszFile[0] = '\0';
1378 SetLastError(CRYPT_E_ASN1_BADTAG);
1381 TRACE("returning %d\n", ret);
1385 BOOL WINAPI WVTAsn1SpcLinkDecode(DWORD dwCertEncodingType,
1386 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1387 void *pvStructInfo, DWORD *pcbStructInfo)
1391 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1392 pvStructInfo, *pcbStructInfo);
1398 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1399 lpszStructType, pbEncoded, cbEncoded, dwFlags, NULL, &bytesNeeded);
1403 *pcbStructInfo = bytesNeeded;
1404 else if (*pcbStructInfo < bytesNeeded)
1406 *pcbStructInfo = bytesNeeded;
1407 SetLastError(ERROR_MORE_DATA);
1412 SPC_LINK *link = pvStructInfo;
1415 (LPWSTR)((BYTE *)pvStructInfo + sizeof(SPC_LINK));
1416 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1417 lpszStructType, pbEncoded, cbEncoded, dwFlags, pvStructInfo,
1424 SetLastError(STATUS_ACCESS_VIOLATION);
1427 TRACE("returning %d\n", ret);
1431 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
1432 DWORD, DWORD, void *, DWORD *);
1435 * The expected tag of the item. If tag is 0, decodeFunc is called
1436 * regardless of the tag value seen.
1438 * A sequence is decoded into a struct. The offset member is the
1439 * offset of this item within that struct.
1441 * The decoder function to use. If this is NULL, then the member isn't
1442 * decoded, but minSize space is reserved for it.
1444 * The minimum amount of space occupied after decoding. You must set this.
1446 * If true, and the tag doesn't match the expected tag for this item,
1447 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
1448 * filled with 0 for this member.
1449 * hasPointer, pointerOffset:
1450 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
1451 * the offset within the struct of the data pointer (or to the
1452 * first data pointer, if more than one exist).
1454 * Used by CRYPT_AsnDecodeSequence, not for your use.
1456 struct AsnDecodeSequenceItem
1460 CryptDecodeObjectFunc decodeFunc;
1464 DWORD pointerOffset;
1468 /* Decodes the items in a sequence, where the items are described in items,
1469 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
1470 * pvStructInfo. nextData is a pointer to the memory location at which the
1471 * first decoded item with a dynamic pointer should point.
1472 * Upon decoding, *cbDecoded is the total number of bytes decoded.
1474 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
1475 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1476 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
1480 DWORD i, decoded = 0;
1481 const BYTE *ptr = pbEncoded;
1483 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
1484 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
1486 for (i = 0, ret = TRUE; ret && i < cItem; i++)
1488 if (cbEncoded - (ptr - pbEncoded) != 0)
1492 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
1495 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
1497 if (ptr[0] == items[i].tag || !items[i].tag)
1499 if (nextData && pvStructInfo && items[i].hasPointer)
1501 TRACE("Setting next pointer to %p\n",
1503 *(BYTE **)((BYTE *)pvStructInfo +
1504 items[i].pointerOffset) = nextData;
1506 if (items[i].decodeFunc)
1509 TRACE("decoding item %d\n", i);
1511 TRACE("sizing item %d\n", i);
1512 ret = items[i].decodeFunc(dwCertEncodingType,
1513 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
1514 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
1515 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
1516 : NULL, &items[i].size);
1519 /* Account for alignment padding */
1520 if (items[i].size % sizeof(DWORD))
1521 items[i].size += sizeof(DWORD) -
1522 items[i].size % sizeof(DWORD);
1523 TRACE("item %d size: %d\n", i, items[i].size);
1524 if (nextData && items[i].hasPointer &&
1525 items[i].size > items[i].minSize)
1526 nextData += items[i].size - items[i].minSize;
1527 ptr += 1 + nextItemLenBytes + nextItemLen;
1528 decoded += 1 + nextItemLenBytes + nextItemLen;
1529 TRACE("item %d: decoded %d bytes\n", i,
1530 1 + nextItemLenBytes + nextItemLen);
1532 else if (items[i].optional &&
1533 GetLastError() == CRYPT_E_ASN1_BADTAG)
1535 TRACE("skipping optional item %d\n", i);
1536 items[i].size = items[i].minSize;
1537 SetLastError(NOERROR);
1541 TRACE("item %d failed: %08x\n", i,
1546 TRACE("item %d: decoded %d bytes\n", i,
1547 1 + nextItemLenBytes + nextItemLen);
1548 ptr += 1 + nextItemLenBytes + nextItemLen;
1549 decoded += 1 + nextItemLenBytes + nextItemLen;
1550 items[i].size = items[i].minSize;
1553 else if (items[i].optional)
1555 TRACE("skipping optional item %d\n", i);
1556 items[i].size = items[i].minSize;
1560 TRACE("item %d: tag %02x doesn't match expected %02x\n",
1561 i, ptr[0], items[i].tag);
1562 SetLastError(CRYPT_E_ASN1_BADTAG);
1567 else if (items[i].optional)
1569 TRACE("missing optional item %d, skipping\n", i);
1570 items[i].size = items[i].minSize;
1574 TRACE("not enough bytes for item %d, failing\n", i);
1575 SetLastError(CRYPT_E_ASN1_CORRUPT);
1580 *cbDecoded = decoded;
1581 TRACE("returning %d\n", ret);
1585 /* This decodes an arbitrary sequence into a contiguous block of memory
1586 * (basically, a struct.) Each element being decoded is described by a struct
1587 * AsnDecodeSequenceItem, see above.
1588 * startingPointer is an optional pointer to the first place where dynamic
1589 * data will be stored. If you know the starting offset, you may pass it
1590 * here. Otherwise, pass NULL, and one will be inferred from the items.
1592 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
1593 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
1594 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1595 void *startingPointer)
1599 TRACE("%p, %d, %p, %d, %08x, %p, %d, %p\n", items, cItem, pbEncoded,
1600 cbEncoded, dwFlags, pvStructInfo, *pcbStructInfo, startingPointer);
1602 if (pbEncoded[0] == ASN_SEQUENCE)
1606 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1608 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
1609 const BYTE *ptr = pbEncoded + 1 + lenBytes;
1611 cbEncoded -= 1 + lenBytes;
1612 if (cbEncoded < dataLen)
1614 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
1616 SetLastError(CRYPT_E_ASN1_CORRUPT);
1620 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
1621 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
1622 if (ret && cbDecoded != dataLen)
1624 TRACE("expected %d decoded, got %d, failing\n", dataLen,
1626 SetLastError(CRYPT_E_ASN1_CORRUPT);
1631 DWORD i, bytesNeeded = 0, structSize = 0;
1633 for (i = 0; i < cItem; i++)
1635 bytesNeeded += items[i].size;
1636 structSize += items[i].minSize;
1639 *pcbStructInfo = bytesNeeded;
1640 else if (*pcbStructInfo < bytesNeeded)
1642 SetLastError(ERROR_MORE_DATA);
1643 *pcbStructInfo = bytesNeeded;
1650 *pcbStructInfo = bytesNeeded;
1651 if (startingPointer)
1652 nextData = startingPointer;
1654 nextData = (BYTE *)pvStructInfo + structSize;
1655 memset(pvStructInfo, 0, structSize);
1656 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
1657 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
1665 SetLastError(CRYPT_E_ASN1_BADTAG);
1668 TRACE("returning %d (%08x)\n", ret, GetLastError());
1672 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
1673 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1674 void *pvStructInfo, DWORD *pcbStructInfo)
1678 TRACE("(%p, %d, 0x%08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
1679 pvStructInfo, *pcbStructInfo);
1681 if (pbEncoded[0] == ASN_BITSTRING)
1683 DWORD bytesNeeded, dataLen;
1685 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1687 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1688 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
1690 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
1692 *pcbStructInfo = bytesNeeded;
1693 else if (*pcbStructInfo < bytesNeeded)
1695 *pcbStructInfo = bytesNeeded;
1696 SetLastError(ERROR_MORE_DATA);
1701 CRYPT_BIT_BLOB *blob;
1703 blob = pvStructInfo;
1704 blob->cbData = dataLen - 1;
1705 blob->cUnusedBits = *(pbEncoded + 1 +
1706 GET_LEN_BYTES(pbEncoded[1]));
1707 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1709 blob->pbData = (BYTE *)pbEncoded + 2 +
1710 GET_LEN_BYTES(pbEncoded[1]);
1714 assert(blob->pbData);
1717 BYTE mask = 0xff << blob->cUnusedBits;
1719 memcpy(blob->pbData, pbEncoded + 2 +
1720 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
1721 blob->pbData[blob->cbData - 1] &= mask;
1729 SetLastError(CRYPT_E_ASN1_BADTAG);
1732 TRACE("returning %d (%08x)\n", ret, GetLastError());
1736 static BOOL WINAPI CRYPT_AsnDecodeSPCLinkPointer(DWORD dwCertEncodingType,
1737 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1738 void *pvStructInfo, DWORD *pcbStructInfo)
1743 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1745 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1747 SPC_LINK **pLink = pvStructInfo;
1749 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType, lpszStructType,
1750 pbEncoded + 1 + lenBytes, dataLen, dwFlags, NULL, &size);
1754 *pcbStructInfo = size + sizeof(PSPC_LINK);
1755 else if (*pcbStructInfo < size + sizeof(PSPC_LINK))
1757 *pcbStructInfo = size + sizeof(PSPC_LINK);
1758 SetLastError(ERROR_MORE_DATA);
1763 *pcbStructInfo = size + sizeof(PSPC_LINK);
1764 /* Set imageData's pointer if necessary */
1765 if (size > sizeof(SPC_LINK))
1767 (*pLink)->u.pwszUrl =
1768 (LPWSTR)((BYTE *)*pLink + sizeof(SPC_LINK));
1770 ret = CRYPT_AsnDecodeSPCLinkInternal(dwCertEncodingType,
1771 lpszStructType, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
1772 *pLink, pcbStructInfo);
1779 BOOL WINAPI WVTAsn1SpcPeImageDataDecode(DWORD dwCertEncodingType,
1780 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1781 void *pvStructInfo, DWORD *pcbStructInfo)
1785 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1786 pvStructInfo, *pcbStructInfo);
1790 struct AsnDecodeSequenceItem items[] = {
1791 { ASN_BITSTRING, offsetof(SPC_PE_IMAGE_DATA, Flags),
1792 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1793 offsetof(SPC_PE_IMAGE_DATA, Flags.pbData), 0 },
1794 { ASN_CONSTRUCTOR | ASN_CONTEXT, offsetof(SPC_PE_IMAGE_DATA, pFile),
1795 CRYPT_AsnDecodeSPCLinkPointer, sizeof(PSPC_LINK), TRUE, TRUE,
1796 offsetof(SPC_PE_IMAGE_DATA, pFile), 0 },
1799 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1800 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1801 pvStructInfo, pcbStructInfo, NULL);
1805 SetLastError(STATUS_ACCESS_VIOLATION);
1808 TRACE("returning %d\n", ret);
1812 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType,
1813 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1814 void *pvStructInfo, DWORD *pcbStructInfo)
1819 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1820 pvStructInfo, *pcbStructInfo);
1822 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1824 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1825 DWORD bytesNeeded = sizeof(LPSTR);
1829 /* The largest possible string for the first two components
1830 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1835 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1836 pbEncoded[1 + lenBytes] / 40,
1837 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1839 bytesNeeded += strlen(firstTwo) + 1;
1840 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1841 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1843 /* large enough for ".4000000" */
1847 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1854 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1857 SetLastError(CRYPT_E_ASN1_CORRUPT);
1864 snprintf(str, sizeof(str), ".%d", val);
1865 bytesNeeded += strlen(str);
1870 *pcbStructInfo = bytesNeeded;
1871 else if (*pcbStructInfo < bytesNeeded)
1873 *pcbStructInfo = bytesNeeded;
1874 SetLastError(ERROR_MORE_DATA);
1882 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1885 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1886 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1888 pszObjId += strlen(pszObjId);
1889 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1890 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1894 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1903 sprintf(pszObjId, ".%d", val);
1904 pszObjId += strlen(pszObjId);
1908 *(LPSTR *)pvStructInfo = NULL;
1909 *pcbStructInfo = bytesNeeded;
1915 static BOOL WINAPI CRYPT_AsnDecodeOid(DWORD dwCertEncodingType,
1916 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1917 void *pvStructInfo, DWORD *pcbStructInfo)
1921 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1922 pvStructInfo, *pcbStructInfo);
1925 SetLastError(CRYPT_E_ASN1_CORRUPT);
1926 else if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1927 ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, lpszStructType,
1928 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
1930 SetLastError(CRYPT_E_ASN1_BADTAG);
1934 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1935 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1936 void *pvStructInfo, DWORD *pcbStructInfo)
1939 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1941 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1942 pvStructInfo, *pcbStructInfo);
1944 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1945 bytesNeeded += cbEncoded;
1947 *pcbStructInfo = bytesNeeded;
1948 else if (*pcbStructInfo < bytesNeeded)
1950 SetLastError(ERROR_MORE_DATA);
1951 *pcbStructInfo = bytesNeeded;
1956 PCRYPT_OBJID_BLOB blob = pvStructInfo;
1958 *pcbStructInfo = bytesNeeded;
1959 blob->cbData = cbEncoded;
1960 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1961 blob->pbData = (LPBYTE)pbEncoded;
1964 assert(blob->pbData);
1965 memcpy(blob->pbData, pbEncoded, blob->cbData);
1971 static BOOL WINAPI CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType,
1972 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1973 void *pvStructInfo, DWORD *pcbStructInfo)
1975 CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue = pvStructInfo;
1976 struct AsnDecodeSequenceItem items[] = {
1977 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId),
1978 CRYPT_AsnDecodeOid, sizeof(LPSTR), FALSE, TRUE,
1979 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId), 0 },
1980 { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value),
1981 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
1982 offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value.pbData), 0 },
1985 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1986 pvStructInfo, *pcbStructInfo);
1988 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1989 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1990 pvStructInfo, pcbStructInfo,
1991 typeValue ? typeValue->pszObjId : NULL);
1994 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
1995 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1996 void *pvStructInfo, DWORD *pcbStructInfo)
1998 CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
2000 struct AsnDecodeSequenceItem items[] = {
2001 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2002 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2003 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2004 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2005 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2006 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2009 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2010 pvStructInfo, *pcbStructInfo);
2012 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2013 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2014 pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
2015 if (ret && pvStructInfo)
2017 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2018 debugstr_a(algo->pszObjId));
2023 static BOOL WINAPI CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType,
2024 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2025 void *pvStructInfo, DWORD *pcbStructInfo)
2027 struct SPCDigest *digest = pvStructInfo;
2028 struct AsnDecodeSequenceItem items[] = {
2029 { ASN_SEQUENCEOF, offsetof(struct SPCDigest, DigestAlgorithm),
2030 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2032 offsetof(struct SPCDigest, DigestAlgorithm.pszObjId), 0 },
2033 { ASN_OCTETSTRING, offsetof(struct SPCDigest, Digest),
2034 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
2035 FALSE, TRUE, offsetof(struct SPCDigest, Digest.pbData), 0 },
2038 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2039 pvStructInfo, *pcbStructInfo);
2041 return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2042 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2043 pvStructInfo, pcbStructInfo,
2044 digest ? digest->DigestAlgorithm.pszObjId : NULL);
2047 BOOL WINAPI WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType,
2048 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2049 void *pvStructInfo, DWORD *pcbStructInfo)
2053 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2054 pvStructInfo, *pcbStructInfo);
2058 struct AsnDecodeSequenceItem items[] = {
2059 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, Data),
2060 CRYPT_AsnDecodeAttributeTypeValue,
2061 sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE), FALSE, TRUE,
2062 offsetof(SPC_INDIRECT_DATA_CONTENT, Data.pszObjId), 0 },
2063 { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm),
2064 CRYPT_AsnDecodeSPCDigest, sizeof(struct SPCDigest),
2066 offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm.pszObjId), 0 },
2069 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2070 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2071 pvStructInfo, pcbStructInfo, NULL);
2075 SetLastError(STATUS_ACCESS_VIOLATION);
2078 TRACE("returning %d\n", ret);
2082 BOOL WINAPI WVTAsn1SpcSpOpusInfoDecode(DWORD dwCertEncodingType,
2083 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2084 void *pvStructInfo, DWORD *pcbStructInfo)
2086 FIXME("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2087 pvStructInfo, *pcbStructInfo);
2091 static BOOL WINAPI CRYPT_AsnDecodeBMPString(DWORD dwCertEncodingType,
2092 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2093 void *pvStructInfo, DWORD *pcbStructInfo)
2096 DWORD bytesNeeded, dataLen;
2098 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2100 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2102 bytesNeeded = dataLen + 2 + sizeof(LPWSTR);
2104 *pcbStructInfo = bytesNeeded;
2105 else if (*pcbStructInfo < bytesNeeded)
2107 *pcbStructInfo = bytesNeeded;
2108 SetLastError(ERROR_MORE_DATA);
2116 *pcbStructInfo = bytesNeeded;
2117 assert(pvStructInfo);
2118 str = *(LPWSTR *)pvStructInfo;
2119 for (i = 0; i < dataLen / 2; i++)
2120 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2121 pbEncoded[1 + lenBytes + 2 * i + 1];
2122 /* Decoded string is always NULL-terminated */
2129 static BOOL CRYPT_AsnDecodeInteger(const BYTE *pbEncoded,
2130 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo)
2133 DWORD bytesNeeded, dataLen;
2135 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2137 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2139 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
2141 *pcbStructInfo = bytesNeeded;
2142 else if (*pcbStructInfo < bytesNeeded)
2144 *pcbStructInfo = bytesNeeded;
2145 SetLastError(ERROR_MORE_DATA);
2150 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
2152 *pcbStructInfo = bytesNeeded;
2153 blob->cbData = dataLen;
2154 assert(blob->pbData);
2159 for (i = 0; i < blob->cbData; i++)
2161 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
2170 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
2171 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2172 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2173 void *pvStructInfo, DWORD *pcbStructInfo)
2176 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
2177 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
2178 DWORD size = sizeof(buf);
2180 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
2181 ret = CRYPT_AsnDecodeInteger(pbEncoded, cbEncoded, 0, buf, &size);
2185 *pcbStructInfo = sizeof(int);
2186 else if (*pcbStructInfo < sizeof(int))
2188 *pcbStructInfo = sizeof(int);
2189 SetLastError(ERROR_MORE_DATA);
2197 *pcbStructInfo = sizeof(int);
2198 if (blob->pbData[blob->cbData - 1] & 0x80)
2200 /* initialize to a negative value to sign-extend */
2205 for (i = 0; i < blob->cbData; i++)
2208 val |= blob->pbData[blob->cbData - i - 1];
2210 memcpy(pvStructInfo, &val, sizeof(int));
2213 else if (GetLastError() == ERROR_MORE_DATA)
2214 SetLastError(CRYPT_E_ASN1_LARGE);
2218 BOOL WINAPI WVTAsn1CatMemberInfoDecode(DWORD dwCertEncodingType,
2219 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2220 void *pvStructInfo, DWORD *pcbStructInfo)
2224 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2225 pvStructInfo, *pcbStructInfo);
2229 struct AsnDecodeSequenceItem items[] = {
2230 { ASN_BMPSTRING, offsetof(CAT_MEMBERINFO, pwszSubjGuid),
2231 CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
2232 offsetof(CAT_MEMBERINFO, pwszSubjGuid), 0 },
2233 { ASN_INTEGER, offsetof(CAT_MEMBERINFO, dwCertVersion),
2234 CRYPT_AsnDecodeInt, sizeof(DWORD),
2235 FALSE, FALSE, 0, 0 },
2238 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2239 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2240 pvStructInfo, pcbStructInfo, NULL);
2244 SetLastError(STATUS_ACCESS_VIOLATION);
2247 TRACE("returning %d\n", ret);
2251 BOOL WINAPI WVTAsn1CatNameValueDecode(DWORD dwCertEncodingType,
2252 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2253 void *pvStructInfo, DWORD *pcbStructInfo)
2257 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2258 pvStructInfo, *pcbStructInfo);
2262 struct AsnDecodeSequenceItem items[] = {
2263 { ASN_BMPSTRING, offsetof(CAT_NAMEVALUE, pwszTag),
2264 CRYPT_AsnDecodeBMPString, sizeof(LPWSTR), FALSE, TRUE,
2265 offsetof(CAT_NAMEVALUE, pwszTag), 0 },
2266 { ASN_INTEGER, offsetof(CAT_NAMEVALUE, fdwFlags),
2267 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2268 { ASN_OCTETSTRING, offsetof(CAT_NAMEVALUE, Value),
2269 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
2270 offsetof(CAT_NAMEVALUE, Value.pbData), 0 },
2273 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2274 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2275 pvStructInfo, pcbStructInfo, NULL);
2279 SetLastError(STATUS_ACCESS_VIOLATION);
2282 TRACE("returning %d\n", ret);
2286 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2287 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2288 void *pvStructInfo, DWORD *pcbStructInfo)
2294 SetLastError(CRYPT_E_ASN1_CORRUPT);
2297 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2299 SetLastError(CRYPT_E_ASN1_CORRUPT);
2302 if (pbEncoded[1] > 1)
2304 SetLastError(CRYPT_E_ASN1_CORRUPT);
2309 *pcbStructInfo = sizeof(BOOL);
2312 else if (*pcbStructInfo < sizeof(BOOL))
2314 *pcbStructInfo = sizeof(BOOL);
2315 SetLastError(ERROR_MORE_DATA);
2320 *pcbStructInfo = sizeof(BOOL);
2321 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2324 TRACE("returning %d (%08x)\n", ret, GetLastError());
2328 BOOL WINAPI WVTAsn1SpcFinancialCriteriaInfoDecode(DWORD dwCertEncodingType,
2329 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2330 void *pvStructInfo, DWORD *pcbStructInfo)
2334 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2335 pvStructInfo, *pcbStructInfo);
2339 struct AsnDecodeSequenceItem items[] = {
2340 { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fFinancialInfoAvailable),
2341 CRYPT_AsnDecodeBool, sizeof(BOOL), FALSE, FALSE, 0, 0 },
2342 { ASN_BOOL, offsetof(SPC_FINANCIAL_CRITERIA, fMeetsCriteria),
2343 CRYPT_AsnDecodeBool, sizeof(BOOL), FALSE, FALSE, 0, 0 },
2346 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2347 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2348 pvStructInfo, pcbStructInfo, NULL);
2352 SetLastError(STATUS_ACCESS_VIOLATION);
2355 TRACE("returning %d\n", ret);